从输入文件扫描时,Scanf忽略换行符

时间:2017-03-02 03:45:24

标签: c input newline scanf

我正在开发一个程序,该程序打算读取多行字符串并将它们分类为字符串数组。

我试图手动读取第一行,并且一旦读取新行字符' \ n'就应该退出循环。当我在终端中手动输入字符串,但是从输入文件(通过终端)读取时,它不会读取换行符,循环继续。

char array[20][20];
char letter = 'a';
for (int i = 0; letter != '\n'; i++) {
    scanf("%s",array[i]);    //store the word into an array of words
    printf("Scanned %s\n",array[i]);
    scanf("%c",&letter);     //look for space or new line character
}

当我手动输入此文本时,它会起作用,但在从文件中读取时不起作用:

word word1 word2
word3 word4 word5

手动输入时,我会输入第一行," word word1 word2",按回车键,它将扫描该行并结束程序。

使用该文件时,它会返回:

$ ./potw18 < input.txt
Scanned word
Scanned word1
Scanned word2
Scanned word3
Scanned word4
Scanned word5
Scanned
Scanned ▒
Scanned
Scanned ▒
Scanned
Scanned ▒8.▒
Scanned
Scanned ▒8.▒
Scanned

继续。

4 个答案:

答案 0 :(得分:2)

我预测文件input.txt有:

  • 第一行末尾的空格(换行除外)和
  • 类似或只是在第二行末尾没有换行符

由于第一点,scanf("%c",&letter);读取除换行符之外的其他内容(例如空格),因此程序继续到第二行。

阅读完最后一个单词后,scanf()文件中没有任何内容可供阅读,因此每次调用时都会返回错误。该计划不会检查这些错误并盲目跋涉。

就我个人而言,我并不是使用scanf()的忠实粉丝,除了快速肮脏的一次性代码。任意输入都容易出错。我建议将行读入缓冲区,然后使用sscanf()strtok()或更好的东西从那里解析(基本上类似于@RoadRunner的答案所说的)。

答案 1 :(得分:1)

您可以使用fgets(3)读取每一行,直到它返回NULL,表示未读取行。您也可以使用getline(3)来执行此操作,这是一个POSIX C函数,旨在有效地读取行。在获取每个单词方面,您可以使用strtok(3)strchr(3)来解析该行上每个空格中的每个单词,并将其安全地添加到您的2d char数组中。使用scanf()只会让你更难做到这一点,正如在@Michael Burr的帖子中彻底证明的那样。

以下是使用stdin从文件中读取行的基本示例,并将找到的单词存储在字符串数组中:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUMWORDS 20
#define WORDLEN 20
#define LINESIZE 100

#define WORDSIZE(x) (sizeof x[0])
#define ARRSIZE(x) (sizeof x / sizeof x[0])

int main(void) {
    char array[NUMWORDS][WORDLEN];
    char line[LINESIZE];
    char *word = NULL, *currline = NULL;
    const char *delim = " \n";
    size_t numwords = 0;

    while (fgets(line, sizeof line, stdin) != NULL) {
        currline = line;

        word = strtok(currline, delim);
        while (word != NULL) {
            if (numwords < ARRSIZE(array) && strlen(word) < WORDSIZE(array)) {
                strcpy(array[numwords], word);
                numwords++;
            }
            word = strtok(NULL, delim);
        }
    }

    for (size_t i = 0; i < numwords; i++) {
        printf("array[%zu] = %s\n", i, array[i]);
    }

    return 0;
}

注意以上代码使用strtok() m,这是一个必须要小心的字符串函数。在这里使用strchr()可能更好。

答案 2 :(得分:0)

使用var baseUrl = API.openweathermap.org/data/2.5/forecast/city; var method = 'GET'; var data = {}; var params = { "name":cityName, "APPID":key_value }; $http({ method: method, url: baseUrl, params : params, data : data }).then(function mySucces(response) { $scope.data = response.data; }, function myError(response) { $scope.data = response.statusText; }); 扫描角色并使用scanf测试角色是否为空白。当角色是换行符时isspace 如果字符不是空格,请使用break将字符替换为输入流,然后ungetc该字。 scanf阻止将太多字符扫描到数组中。

%19s

答案 3 :(得分:-1)

char array[20][20];
char letter = 'a';
for (int i = 0; letter != '\n'; i++) {
   gets(array);    //store the word into an array of words
   letter = array[i];
   scanf("%c",&letter);    
}

使用gets它应该有用。