如何在c中扫描一行的其余部分

Jam*_*mes 4 c

我在文件Eg中有几行整数

100 20 300 20 9 45 -1
101 80 80 2 80 2 50 3 70 -1
Run Code Online (Sandbox Code Playgroud)

我想读取前2个字符并将它们存储在整数变量中,然后将其余字符存储在一个字符串中,我可以稍后迭代.

do {
    fscanf(file, "%d %d", &var1,&var2);
    }while(!feof(file));
Run Code Online (Sandbox Code Playgroud)

现在我想扫描剩余的线,移动到下一行并重复.但我不知道如何将其余部分扫描成var3字符串

..有任何想法吗?

pax*_*blo 7

这是你做的第一件事.scanf("%s")除非您完全控制输入​​数据,否则不要使用任何想法.否则你会打开缓冲区溢出.

这个答案显示了一种安全fgets的用户输入方式,提供缓冲区溢出检测/避免和行清除,可以很容易地适应任何输入流.

一旦你将行(和行)作为一个字符串,并因此知道它的最大大小,你可以简单地使用:

char strBuff[1000]. str1[1000]; // Ensure both big enough.
:
// Use /getLine/fgets to get the line into strBuff.
:
int numScanned = sscanf (strBuff, "%d %d %[^\n]", &int1, &int2, str1);
Run Code Online (Sandbox Code Playgroud)

什么%[^\n]格式说明的作用是扫描任何数目的非换行符成一个字符串:[]代表一个字符类,则^是指"匹配所有以下字符,并用于(非)匹配的字符是换行\n.

标准引用在本答案(a)的底部.


例如,使用该功能:

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

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}
Run Code Online (Sandbox Code Playgroud)

使用以下程序:

int main (void) {
    int rc, numScanned, int1, int2;;
    char strBuff[100], str1[100];

    rc = getLine ("Yes> ", strBuff, sizeof(strBuff));
    if (rc == NO_INPUT) {
        // Extra NL since my system doesn't output that on EOF.
        printf ("\nNo input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long [%s]\n", strBuff);
        return 1;
    }

    printf ("OK [%s]\n", strBuff);

    numScanned = sscanf (strBuff, "%d %d %[^\n]", &int1, &int2, str1);
    printf ("numScanned = %d\n", numScanned);
    printf ("int1       = %d\n", int1);
    printf ("int2       = %d\n", int2);
    printf ("str1       = [%s]\n", str1);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

Yes> 100 20 300 20 9 45 -1 blah blah blah
OK [100 20 300 20 9 45 -1 blah blah blah]
numScanned = 3
int1       = 100
int2       = 20
str1       = [300 20 9 45 -1 blah blah blah]
Run Code Online (Sandbox Code Playgroud)

(一)部分7.20.6.2 The fscanf functionC11(虽然这是不变的C99)指出这个有关[格式说明,稍微改写去除不相关的多字节的东西:

[格式说明从相匹配的一组预期的字符(在扫描集)的字符的非空序列.

相应的参数应该是指向大小足以接受序列的字符数组的初始元素的指针,以及将自动添加的终止空字符.

转换说明符包括格式字符串中的所有后续字符,包括匹配的右括号(]).

括号(扫描列表)之间的字符组成扫描集,除非左括号后面的字符是抑扬符(^),在这种情况下,扫描集包含在旋转和右括号之间的扫描列表中不出现的所有字符.如果转换说明符以[]或开头[^],则右括号字符位于扫描列表中,下一个右括号字符是结束规范的匹配右括号; 否则第一个右括号字符是结束规范的字符.

  • @James着名的遗言.;-) (4认同)