c-输入行末尾的空格导致while循环比它应该进行的多进行一次

  • 本文关键字:一次 循环 空格 while c scanf
  • 更新时间 :
  • 英文 :

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int a = 0, f = 0;
char ch[1];
char arr[1000];
while (f < 3) {
while (((*ch = getchar()) != 10))
{
scanf("%9s", &(arr[a]));
scanf("%9s", &(arr[a + 1]));
a += 2;
}
f++;
}
for (int i = 0; i < a; i++) {
printf("%sn", &arr[i]);
}
return 0;
}

这个代码应该收集输入,比如:

1 4 green 4 green 1 blue 2 blue 4 blue 5 blue 7 blue  5 red 7 red 1 violet 2 violet 4 violet 5 violet 7 violet 
1 
2 4 green 4 green  7 blue 1 red 2 red 4 red 5 red 7 red 1 violet 2 violet 4 violet 5 violet 7 violet
2 
3 4 green 4 green 1 blue 2 blue 4 blue  7 blue 1 red 2 red 4 red 5 red 7 red  5 violet 7 violet
3 

首先,有一些数字,然后是一个数字和一个单词。我不知道会有多少次,但我知道输入行的数量。我遇到的问题是,当在控制台中按下"回车"之前,输入行的末尾有一个空格时,程序会一直等待更多的输入。我不知道如何消除这种情况,尤其是在输入的最后一行,因为在最后一行的末尾放空格会导致程序永远等待用户键入内容。

让我们解开您的代码。

您正在使用getchar来查找行的末尾,但它会吞下该字符。scanf看不到;0123456789";CCD_ 3将吃掉0。您可以使用putchar将其放回原处,但这完全没有必要。

scanf("%9s", &(arr[a]));
scanf("%9s", &(arr[a + 1]));

这是从输入中读取最多九个字符,并将其粘贴到字符串arr中。然后,它从输入中再读取9个字符,并覆盖刚刚读取的8个字符。

要穿过它,我们假设这条线是";0123456789bcdefghijklmno";

  • a:0
  • stdin:";0123456789bcdefghijklmno">
  • arr:";垃圾垃圾arr未初始化

getchar()从stdin读取0。

  • a:0
  • stdin:";123456789bcdefghijklmno">
  • arr:";垃圾垃圾

scanf("%9s", &(arr[a]))从stdin读取123456789,并将其放入arr,从a开始,即0。

  • a:0
  • stdin:";abcdefghijklmno">
  • arr:";123456789\0垃圾箱垃圾">

scanf("%9s", &(arr[a + 1]))从stdin读取abcdefghi,并将其放入arr,从a + 1开始,这是1,覆盖了除了刚刚写入arr的第一个字符之外的所有字符。

  • a:0
  • stdin:";jklmno">
  • arr:";1abdedfghi \0百吉垃圾">

CCD_;1abdedfghi";。


char arr[1000]为堆栈分配999个字符(加上一个空字节(的单个字符串的空间。我想你的意思是arr是一个由1000个字符串组成的数组,每个字符串至少可以容纳9个字符加上空字节。这是char arr[1000][10]

scanf有很多问题,尝试用getchar逐行读取也是如此。相反,通常最好将带有fgets的行读取到缓冲区中,并使用sscanf或其他字符串解析函数解析该行。这避免了挂起等待输入或未知行大小的许多问题。

在这种情况下,使用strtok(STRing TOKenizer(在空白处拆分行。strtok的行为有点奇怪,因为它有自己的内部缓冲区。它也不分配新内存,而是返回原始行中的指针。空格被替换为空字节,所以看起来一次只得到一个令牌。使用strdup将单词复制到数组中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// A single line buffer to reuse.
// BUFSIZ is the size of the input buffer and a good size to choose.
char line[BUFSIZ];
// An array for 1000 strings.
// No memory is allocated for the strings themselves.
// We'll allocate as needed.
//
// Note: a real problem would not allocate a fixed size array.
// It would extend `words` as needed.
// You'll learn how to do that that later.
char *words[1000];
// Track how many words are in the words array.
int num_words = 0;
// Read at most 3 lines
for(int i = 0; i < 3; i++) {
// Read a line. Exit the loop early if there's no more lines.
if( !fgets(line, sizeof(line), stdin) ) {
break;
}
// Split the line on whitespace.
// fgets() does not strip newlines.
// We must include newline else it will be considered a word.
for(
char *word = strtok(line, " tn");
word;
word = strtok(NULL, " tn")
) {
// word is a pointer to memory inside line.
// The whitespace has been replaced by a null byte so we can
// read a single word. We could store that and save memory,
// but `line` will be reused to read the next line and
// the previous words will be overwritten.
// So we need to copy the word. `strdup` allocates just the
// right amount of memory.
words[num_words] = strdup(word);
num_words++;
}
}
for (int i = 0; i < num_words; i++) {
printf("%sn", words[i]);
}
return 0;
}

你应该能够根据你的具体任务调整基本代码,阅读一行行单词。

最新更新