c语言中比较特殊的输入函数

news2024/11/17 14:42:11

目录

一.getchar()函数

1.基本功能

2.使用方法

(1).读取单个字符

(2).读取多个字符(直到遇到换行符)

(3).处理输入中的空白字符

3.返回值

4.应用场景

5.注意事项

二.fgets()函数

1.函数原型

2.工作原理

3.使用示例

(1).从标准输入读取一行字符串

(2).从文件中读取内容

4.处理换行符

5.与其他输入函数的比较

(1). fgets vs gets

(2). fgets vs scanf

(3). fgets vs fgetc

6、常见错误和注意事项

(1). 忘记检查返回值

(2). 未正确处理换行符

(3). 缓冲区大小不足

(4). 多次读取时的缓冲区残留

7.综合示例

三.sscanf函数

1.函数原型

2.工作原理

(1).从字符串中解析数据

3.常见用法和注意事项

(1). 解析特定格式的字符串

(2). 处理多余的输入

(3). 不匹配的格式

(4). 忽略特定数据

(5). 返回值处理

4.常见错误和陷阱

(1). 未匹配到预期的数据

(2). 忘记检查返回值

(3). 缓冲区溢出

(4). 处理多余输入

5.sscanf 与其他输入函数的比较

(1). sscanf vs scanf

(2). sscanf vs fscanf

(3). sscanf vs strtok

6.综合示例

四.fscanf()函数

1.函数原型

2.工作原理

3.常用用法和注意事项

(1). 读取一行数据

(2). 文件指针位置

(3). 遇到EOF

(4). 忽略特定数据

(5). 返回值处理

(6). 处理多余输入

4.常见错误和陷阱

(1). 格式不匹配

(2). 忘记检查返回值

(3). 文件结束符

5.fscanf 与其他输入函数的比较

(1). fscanf vs scanf

(2). fscanf vs sscanf

(3). fscanf vs fgets

6.综合示例


一.getchar()函数

getchar()是C语言中的一个标准库函数,用于从标准输入(通常是键盘)读取一个字符。它是stdio.h库的一部分,常用于简单的字符输入操作。

1.基本功能

getchar()读取标准输入中的下一个字符,并将其作为一个int类型的值返回。尽管返回值是int类型,但它实际上是一个字符的ASCII值

2.使用方法

int ch = getchar();

在这段代码中,getchar()从标准输入中读取一个字符,并将其返回的字符值存储在ch变量中。

示例:

(1).读取单个字符

#include <stdio.h>

int main() {
    int ch;
    
    printf("请输入一个字符: ");
    ch = getchar();
    
    printf("你输入的字符是: %c\n", ch);
    
    return 0;
}

解释:

  • 程序等待用户输入一个字符。用户输入的字符被getchar()读取并存储在ch中。
  • printf函数随后输出用户输入的字符。

(2).读取多个字符(直到遇到换行符)

#include <stdio.h>

int main() {
    int ch;
    
    printf("请输入一行文字,按回车结束: ");
    
    while ((ch = getchar()) != '\n' && ch != EOF) {
        printf("读取字符: %c\n", ch);
    }
    
    printf("输入结束。\n");
    
    return 0;
}

解释:

  • 程序使用while循环来读取字符,直到遇到换行符('\n')或文件结束符(EOF)。
  • 每次读取的字符都会被输出。

(3).处理输入中的空白字符

#include <stdio.h>

int main() {
    int ch;

    printf("请输入字符,输入结束请按 Ctrl+D (Linux) 或 Ctrl+Z (Windows):\n");

    while ((ch = getchar()) != EOF) {
        if (ch == ' ' || ch == '\n' || ch == '\t') {
            printf("[空白字符]\n");
        } else {
            printf("读取字符: %c\n", ch);
        }
    }

    printf("输入结束。\n");
    
    return 0;
}

解释:

  • 这个程序读取用户输入的每个字符,并检查它是否是空白字符(空格、换行符、制表符)。
  • 如果是空白字符,程序会输出[空白字符],否则输出字符本身。
  • 当用户按下Ctrl+DCtrl+Z时,输入结束。

3.返回值

  • 读取的字符: 如果读取成功,getchar()返回读取的字符的ASCII值。例如,如果用户输入字符'A'getchar()将返回值65(即'A'的ASCII码)。

  • EOF (End of File): 如果在读取时遇到文件结束符(通常是在控制台输入时按下Ctrl+DCtrl+Z),getchar()将返回常量EOF,其值通常为-1EOF用于指示输入的结束或错误情况。

4.应用场景

  • 简单字符输入: getchar()通常用于简单的字符输入操作,例如读取单个字符或控制台中的用户输入。

  • 处理空白字符: 当你需要明确处理空白字符(例如空格、制表符或换行符)时,getchar()特别有用。相比于scanfgetchar()不会跳过空白字符,因此你可以逐字符地处理输入。

  • 控制输入流: getchar()在处理输入流时非常灵活,可以用于跳过不需要的字符。例如,在多行输入或复杂输入格式的情况下,它可以帮助你控制和过滤输入内容。

5.注意事项

  • 返回类型为int: 尽管getchar()用于读取单个字符,但它的返回类型是int而不是char。这样设计是为了能够返回EOF来表示文件结束或错误。为了避免潜在的错误,通常应该使用int类型来存储getchar()的返回值。

  • 缓冲区问题: 在控制台输入时,用户输入的内容通常会先进入缓冲区。当按下回车键时,缓冲区中的内容才会被getchar()逐个读取。因此,getchar()不会在每个字符输入时立即返回,而是等待用户按下回车键。

  • 错误处理: 当使用getchar()时,程序应该考虑EOF的可能性,尤其是在文件输入或批处理输入的情况下。忽略这一点可能会导致程序未正确处理输入结束的情况。

二.fgets()函数

fgets 是C语言中用于从文件流中读取一行字符串的标准库函数。它提供了一种安全、方便的方法来读取输入,避免了诸如缓冲区溢出等常见问题。fgets 通常用于读取用户输入、从文件中读取数据等场景。

1.函数原型

char *fgets(char *str, int n, FILE *stream);

  • str: 指向字符数组的指针,fgets 会将读取到的字符串存储在该数组中。
  • n: 要读取的最大字符数,包括结尾的空字符 \0。也就是说,fgets 最多读取 n-1 个字符。
  • stream: 输入流指针,指明从哪个流中读取数据。常见的流有标准输入流 stdin,文件流等。

返回值

  • 成功: 返回指向读取字符串的指针,即参数 str
  • 失败或到达文件末尾: 返回 NULL

2.工作原理

fgets 函数从指定的输入流 stream 中读取字符,并将其存储到 str 指向的字符数组中,直到发生以下任一情况:

  1. 读取了 (n - 1) 个字符: 为了保证字符串以 \0 结尾,fgets 最多读取 n - 1 个字符。
  2. 遇到换行符 \n: fgets 会读取换行符,并将其存储在 str 中。
  3. 到达文件末尾 EOF: 如果在读取过程中遇到文件末尾,读取操作结束。

读取完成后,fgets 会在读取的字符串末尾自动添加一个空字符 \0,以表示字符串的结束。

3.使用示例

(1).从标准输入读取一行字符串

#include <stdio.h>

int main() {
    char buffer[100];

    printf("请输入一行文本:");
    if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        printf("您输入的是:%s", buffer);
    } else {
        printf("读取输入时发生错误。\n");
    }

    return 0;
}

解释:

  • fgets(buffer, sizeof(buffer), stdin) 从标准输入读取最多 99 个字符(保留1个字符给 \0),并存储在 buffer 中。
  • 如果读取成功,程序会输出用户输入的内容。

注意: 由于 fgets 会将换行符 \n 一并读取并存储,如果不想要这个换行符,需要手动去除。

(2).从文件中读取内容

#include <stdio.h>

int main() {
    FILE *fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char line[256];
    while (fgets(line, sizeof(line), fp) != NULL) {
        printf("%s", line);
    }

    fclose(fp);
    return 0;
}

解释:

  • 打开名为 example.txt 的文件,读取其中的内容并逐行打印到标准输出。
  • fgets 在每次循环中读取一行内容,直到文件结束。

4.处理换行符

正如前面提到的,fgets 会将输入中的换行符 \n 一并读取并存储在目标字符串中。如果在处理时不需要这个换行符,可以使用以下方法去除:

方法1:手动检查并替换

size_t len = strlen(buffer);
if (len > 0 && buffer[len - 1] == '\n') {
    buffer[len - 1] = '\0';
}

解释:

  • 首先获取字符串的长度 len
  • 如果最后一个字符是 \n,将其替换为 \0

方法2:使用 strcspn 函数

buffer[strcspn(buffer, "\n")] = '\0';

解释:

  • strcspn 函数返回 buffer 中第一个匹配 \n 的位置索引,然后将该位置的字符替换为 \0

5.与其他输入函数的比较

(1). fgets vs gets

  • gets: 从标准输入读取一行,直到遇到换行符或文件结束符。不安全,因为无法指定读取的最大长度,容易导致缓冲区溢出。

  • fgets: 可以指定最大读取长度,安全性更高。建议始终使用 fgets 代替 gets

(2). fgets vs scanf

  • scanf: 按照指定的格式从输入中读取数据,默认会忽略空白字符,读取字符串时会在遇到空白字符时停止。

  • fgets: 读取整行输入,包括空白字符和换行符,更适合读取包含空格的字符串

示例:

char str1[100], str2[100];

// 使用 scanf
scanf("%s", str1);
// 输入:Hello World
// str1 的值为:"Hello"

// 使用 fgets
fgets(str2, sizeof(str2), stdin);
// 输入:Hello World
// str2 的值为:"Hello World\n"

(3). fgets vs fgetc

  • fgetc: 每次从指定流中读取一个字符,适合逐字符处理输入。

  • fgets: 一次读取一行或指定长度的字符串,效率更高。

6、常见错误和注意事项

(1). 忘记检查返回值

在使用 fgets 时,应该始终检查其返回值,以确保读取成功。

错误示例:

fgets(buffer, sizeof(buffer), stdin);
// 未检查返回值,可能导致程序处理空指针

正确示例:

if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    // 处理读取的数据
} else {
    // 错误处理
}

(2). 未正确处理换行符

如前所述,fgets 会保留输入中的换行符,如果不想要这个换行符,需要手动去除。

(3). 缓冲区大小不足

确保提供给 fgets 的缓冲区足够大,以容纳预期的输入数据和结尾的空字符。

错误示例:

char buffer[10];
fgets(buffer, 100, stdin); // 错误:缓冲区只有10个字节,却试图读取100个字符

正确示例:

char buffer[100];
fgets(buffer, sizeof(buffer), stdin); // 正确:缓冲区大小与读取长度匹配

(4). 多次读取时的缓冲区残留

在某些情况下,输入流中可能残留未读取的字符,需要在下一次读取前清空缓冲区。

char buffer1[50], buffer2[50];

printf("输入第一行:");
fgets(buffer1, sizeof(buffer1), stdin);

printf("输入第二行:");
fgets(buffer2, sizeof(buffer2), stdin);

如果在第一次输入时输入的字符超过了 buffer1 的大小,剩余的字符会留在输入缓冲区中,影响第二次读取。为避免这种情况,可以在每次读取后清空缓冲区。

清空缓冲区的方法:

int c;
while ((c = getchar()) != '\n' && c != EOF);

7.综合示例

示例:读取用户输入并处理

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

int main() {
    char name[50];
    int age;
    char input[100];

    // 读取姓名
    printf("请输入您的姓名:");
    if (fgets(name, sizeof(name), stdin) != NULL) {
        // 去除换行符
        name[strcspn(name, "\n")] = '\0';
    } else {
        printf("读取姓名失败。\n");
        return 1;
    }

    // 读取年龄
    printf("请输入您的年龄:");
    if (fgets(input, sizeof(input), stdin) != NULL) {
        // 将字符串转换为整数
        age = atoi(input);
    } else {
        printf("读取年龄失败。\n");
        return 1;
    }

    printf("姓名:%s,年龄:%d\n", name, age);

    return 0;
}

解释:

  • 首先使用 fgets 读取用户的姓名,并去除结尾的换行符。
  • 然后再次使用 fgets 读取用户的年龄输入,并使用 atoi 将其转换为整数。
  • 最后输出用户输入的信息。

三.sscanf函数

sscanf 是C语言中用于从字符串中读取并解析数据的标准库函数。它的作用类似于 scanf,但 sscanf字符串中读取数据,而 scanf 是从标准输入中读取数据。sscanf 非常适合从已知格式的字符串中提取数值、字符等数据。

1.函数原型

int sscanf(const char *str, const char *format, ...);

  • str: 要解析的源字符串。sscanf 会从这个字符串中读取数据。
  • format: 格式字符串,指定了要解析的数据格式。它的语法和 scanf 的格式字符串相同,包括各种格式说明符(如 %d, %s, %f 等)。
  • ...: 可变参数列表,提供用于存储从字符串中读取的数据的指针。

返回值

  • 成功: 返回成功读取并匹配的项数
  • 失败: 返回 EOF,如果在解析过程中遇到错误或在尝试读取时到达字符串末尾

2.工作原理

sscanf 函数根据 format 字符串中的格式说明符,从源字符串 str 中逐一读取和解析数据。每个格式说明符都对应于一个传入的变量地址,sscanf 将解析后的数据存储在这些变量中。

格式说明符示例

  • %d: 读取一个整数。
  • %f: 读取一个浮点数。
  • %s: 读取一个字符串,遇到空白字符(如空格、换行)时停止。
  • %c: 读取单个字符。

示例:

(1).从字符串中解析数据

#include <stdio.h>

int main() {
    const char *str = "100 3.14 hello";
    int num;
    float pi;
    char word[20];

    int count = sscanf(str, "%d %f %s", &num, &pi, word);

    printf("读取到 %d 项数据:\n", count);
    printf("整数: %d\n", num);
    printf("浮点数: %.2f\n", pi);
    printf("字符串: %s\n", word);

    return 0;
}

输出:

读取到 3 项数据:
整数: 100
浮点数: 3.14
字符串: hello

解释:

  • sscanf 解析字符串 "100 3.14 hello",并将数据分别存储在 num, pi, word 中。
  • 返回值 count 表示成功读取了3项数据。

3.常见用法和注意事项

(1). 解析特定格式的字符串

sscanf 特别适用于解析具有固定格式的字符串,比如日期、时间、IP地址等。

示例:解析日期

#include <stdio.h>

int main() {
    const char *date = "2024-08-17";
    int year, month, day;

    sscanf(date, "%d-%d-%d", &year, &month, &day);

    printf("年: %d, 月: %d, 日: %d\n", year, month, day);

    return 0;
}

输出:

年: 2024, 月: 8, 日: 17

解释:

  • 解析字符串 "2024-08-17" 中的年份、月份和日期,并分别存储在 year, month, day 中。

(2). 处理多余的输入

如果源字符串中的内容多于格式说明符指定的内容,sscanf 只会处理指定的部分,忽略其余部分。

示例:部分解析字符串

#include <stdio.h>

int main() {
    const char *str = "42 3.14 some extra text";
    int num;
    float pi;

    int count = sscanf(str, "%d %f", &num, &pi);

    printf("读取到 %d 项数据:\n", count);
    printf("整数: %d\n", num);
    printf("浮点数: %.2f\n", pi);

    return 0;
}

输出:

读取到 2 项数据:
整数: 42
浮点数: 3.14

解释:

  • sscanf 只解析了前两个数据项(整数和浮点数),忽略了字符串末尾的额外内容。

(3). 不匹配的格式

如果字符串中的内容与格式说明符不匹配,sscanf 会停止解析,并返回已成功读取的项数。

示例:格式不匹配

#include <stdio.h>

int main() {
    const char *str = "hello 3.14";
    int num;
    float pi;

    int count = sscanf(str, "%d %f", &num, &pi);

    printf("读取到 %d 项数据:\n", count);
    return 0;
}

输出:

读取到 0 项数据:

(4). 忽略特定数据

sscanf 还可以使用 * 来忽略某些输入数据,不存储在任何变量中。

示例:忽略数据

#include <stdio.h>

int main() {
    const char *str = "42 skip this 3.14";
    int num;
    float pi;

    sscanf(str, "%d %*s %f", &num, &pi);

    printf("整数: %d\n", num);
    printf("浮点数: %.2f\n", pi);

    return 0;
}

输出:

整数: 42
浮点数: 3.14

解释:

  • sscanf 使用 %*s 忽略了 "skip this" 字符串部分,只提取了整数和浮点数。

(5). 返回值处理

sscanf 的返回值用于检查是否成功解析了预期的项数。在实际编程中,应该根据返回值来验证解析操作的成功与否。

示例:检查返回值

#include <stdio.h>

int main() {
    const char *str = "100 3.14";
    int num;
    float pi;

    int result = sscanf(str, "%d %f", &num, &pi);

    if (result == 2) {
        printf("成功读取两个数值:%d 和 %.2f\n", num, pi);
    } else {
        printf("解析失败,已成功读取 %d 项数据。\n", result);
    }

    return 0;
}

输出:

成功读取两个数值:100 和 3.14

解释:

  • 如果 sscanf 成功解析了两个值,程序输出成功消息。否则,输出失败消息。

4.常见错误和陷阱

(1). 未匹配到预期的数据

如果输入字符串的格式与格式说明符不匹配,sscanf 会停止解析,返回已经成功解析的项数。确保格式字符串与输入字符串的格式一致非常重要。

(2). 忘记检查返回值

忽略 sscanf 的返回值可能导致错误的程序行为。检查返回值是验证解析操作成功与否的关键步骤。

(3). 缓冲区溢出

当读取字符串数据(如使用 %s)时,确保目标缓冲区有足够的空间以避免溢出。使用长度限制格式符号(如 %99s)可以防止缓冲区溢出。

(4). 处理多余输入

如果 sscanf 只读取了部分输入数据,而程序的逻辑依赖于完整的数据解析,可能会导致问题。合理设计格式说明符和字符串输入非常重要。

5.sscanf 与其他输入函数的比较

(1). sscanf vs scanf

  • scanf: 从标准输入中读取数据,适用于直接的用户输入操作。

  • sscanf: 从字符串中读取数据,适用于解析已经存在的字符串内容。

(2). sscanf vs fscanf

  • fscanf: 从文件流中读取数据,适用于从文件中解析数据。

  • sscanf: 从字符串中读取数据,适用于解析内存中的字符串。

(3). sscanf vs strtok

  • strtok: 用于分割字符串,可以按指定的分隔符逐一提取子字符串。

  • sscanf: 直接解析字符串中的数据,并将其转换为相应的数据类型。

6.综合示例

示例:解析复杂字符串

#include <stdio.h>

int main() {
    const char *str = "Name: John Doe, Age: 30, Score: 85.5";
    char name[50];
    int age;
    float score;

    int count = sscanf(str, "Name: %[^,], Age: %d, Score: %f", name, &age, &score);

    if (count == 3) {
        printf("姓名: %s\n", name);
        printf("年龄: %d\n", age);
        printf("分数: %.1f\n", score);
    } else {
        printf("解析字符串失败。\n");
    }

    return 0;
}

输出:

姓名: John Doe
年龄: 30
分数: 85.5

解释:

  • 使用 sscanf 从格式化字符串中提取姓名、年龄和分数。%[^,] 格式说明符用于读取直到遇到逗号 , 的所有字符,这样可以处理包含空格的姓名。

四.fscanf()函数

fscanf 是C语言中用于从文件读取并解析数据的标准库函数。它的作用类似于 scanf,但 fscanf 从文件流中读取数据,而 scanf从标准输入中读取数据fscanf 适合从文件中逐行或逐项读取并解析数据。

1.函数原型

int fscanf(FILE *stream, const char *format, ...);

参数说明

  • stream: 文件指针,指向要读取的文件流(通常是通过 fopen 打开的文件)。
  • format: 格式字符串,指定了要解析的数据格式。它的语法和 scanf 的格式字符串相同,包括各种格式说明符(如 %d, %s, %f 等)。
  • ...: 可变参数列表,提供用于存储从文件中读取的数据的指针。

返回值

  • 成功: 返回成功读取并匹配的项数
  • 失败: 如果遇到文件结束符 EOF,则返回 EOF。如果遇到错误,返回负数。

2.工作原理

fscanf 函数根据 format 字符串中的格式说明符,从文件流 stream 中逐一读取和解析数据。每个格式说明符都对应于一个传入的变量地址,fscanf 将解析后的数据存储在这些变量中。

格式说明符示例

  • %d: 读取一个整数。
  • %f: 读取一个浮点数。
  • %s: 读取一个字符串,遇到空白字符(如空格、换行)时停止。
  • %c: 读取单个字符。

示例:从文件中解析数据

假设有一个文本文件 data.txt,内容如下:

42 3.14 hello
#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r"); // 打开文件进行读取
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int num;
    float pi;
    char word[20];

    int count = fscanf(file, "%d %f %s", &num, &pi, word);

    printf("读取到 %d 项数据:\n", count);
    printf("整数: %d\n", num);
    printf("浮点数: %.2f\n", pi);
    printf("字符串: %s\n", word);

    fclose(file); // 关闭文件
    return 0;
}

输出:

读取到 3 项数据:
整数: 42
浮点数: 3.14
字符串: hello

解释:

  • fscanf 从文件 data.txt 中解析数据,并将数据分别存储在 num, pi, word 中。
  • 返回值 count 表示成功读取了3项数据。

3.常用用法和注意事项

(1). 读取一行数据

fscanf 通常按格式说明符读取数据,直到匹配结束,或者遇到文件结束符 EOF。它不会自动处理行结束符,因此如果要按行读取数据,可以结合 fgetssscanf 使用。

示例:逐行读取数据

假设文件 data.txt 内容如下:

42 3.14 hello
43 2.71 world
#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int num;
    float pi;
    char word[20];

    while (fscanf(file, "%d %f %s", &num, &pi, word) != EOF) {
        printf("整数: %d, 浮点数: %.2f, 字符串: %s\n", num, pi, word);
    }

    fclose(file);
    return 0;
}

输出:

整数: 42, 浮点数: 3.14, 字符串: hello
整数: 43, 浮点数: 2.71, 字符串: world

(2). 文件指针位置

fscanf 读取数据后,文件指针会移动到读取结束的位置。下一次调用 fscanf 会从当前文件指针位置继续读取。

(3). 遇到EOF

fscanf 遇到文件结束符 EOF 时,它会返回 EOF,通常是 -1。这可以用来判断是否已经读取到文件末尾。

(4). 忽略特定数据

类似于 sscanffscanf 也可以使用 * 来忽略某些输入数据,而不存储在任何变量中。

示例:忽略数据

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int num;
    float pi;

    while (fscanf(file, "%d %*s %f", &num, &pi) != EOF) {
        printf("整数: %d, 浮点数: %.2f\n", num, pi);
    }

    fclose(file);
    return 0;
}

解释:

  • fscanf 使用 %*s 忽略了字符串部分,只提取了整数和浮点数。

(5). 返回值处理

sscanf 类似,fscanf 的返回值表示成功读取并解析的数据项数。在实际编程中,应该根据返回值来验证解析操作的成功与否。

示例:检查返回值

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    int num;
    float pi;

    while (fscanf(file, "%d %f", &num, &pi) == 2) { // 期望成功读取2项数据
        printf("整数: %d, 浮点数: %.2f\n", num, pi);
    }

    fclose(file);
    return 0;
}

解释:

  • 只有在成功解析了两个值时才输出结果。如果 fscanf 未能成功读取两个值,将停止读取。

(6). 处理多余输入

如果文件中的内容多于格式说明符指定的内容,fscanf 只会处理指定的部分,忽略其余部分。

4.常见错误和陷阱

(1). 格式不匹配

如果文件中的内容与格式说明符不匹配,fscanf 会停止解析,并返回已成功读取的项数。确保格式字符串与文件内容格式一致非常重要。

(2). 忘记检查返回值

忽略 fscanf 的返回值可能导致错误的程序行为。检查返回值是验证解析操作成功与否的关键步骤。

(3). 文件结束符

fscanf 在读取到文件结束符 EOF 时会返回 EOF,这与常规的返回值检查不同,处理文件结束符时需要特别注意。

5.fscanf 与其他输入函数的比较

(1). fscanf vs scanf

  • scanf: 从标准输入中读取数据,适用于直接的用户输入操作。

  • fscanf: 从文件流中读取数据,适用于从文件中解析数据。

(2). fscanf vs sscanf

  • sscanf: 从字符串中读取数据,适用于解析内存中的字符串。

  • fscanf: 从文件流中读取数据,适用于从文件中解析数据。

(3). fscanf vs fgets

  • fgets: 从文件中读取一整行字符串,适用于逐行读取文件内容,通常结合 sscanf 使用以进一步解析数据。

  • fscanf: 按照格式说明符从文件中读取数据,适用于逐项解析数据。

6.综合示例

示例:从文件中读取并解析数据

假设有一个文本文件 students.txt,内容如下:

John 20 85.5
Alice 22 90.0
Bob 21 78.5
#include <stdio.h>

int main() {
    FILE *file = fopen("students.txt", "r");
    if (file == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char name[50];
    int age;
    float score;

    while (fscanf(file, "%s %d %f", name, &age, &score) == 3) {
        printf("姓名: %s, 年龄: %d, 分数: %.1f\n", name, age, score);
    }

    fclose(file);
    return 0;
}

输出

姓名: John, 年龄: 20, 分数: 85.5
姓名: Alice, 年龄: 22, 分数: 90.0
姓名: Bob, 年龄: 21, 分数: 78.5

解释:

  • fscanf 从文件 students.txt 中解析每一行数据,并输出到屏幕上。它通过格式说明符 %s %d %f 解析每行中的姓名、年龄和分数。

完!

一键三连支持一下吧,非常感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2049464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qt笔记之qml中的TextEdit、TextInput、TextArea、TextField的区别

qt笔记之qml中的TextEdit、TextInput、TextArea、TextField的区别 code review! 文章目录 qt笔记之qml中的TextEdit、TextInput、TextArea、TextField的区别一.对比二.C环境中类似功能的控件 一.对比 TextEdit、TextInput、TextArea和TextField都是用于文本输入的组件&#…

基于PostGIS(Postgres)+Node.js实现的xyz瓦片地图服务器

背景介绍 前两天研究GeoServer发布存储在PostGIS中栅格数据&#xff0c;最终目的是想在PostGIS中存储金字塔瓦片&#xff0c;用GeoServer发布&#xff0c;但是最后经过研究不改GeoServer源码的情况下&#xff0c;好像只支持将大图tif存在PostGIS数据库中进行发布&#xff0c;金…

XSS漏洞复现(包括xssgame和三个高级xss漏洞)

文章目录 XSS GAME1、Ma Spaghet!2、Jefff3、Ugandan Knuckles4、Ricardo Milos5、Ah Thats Hawt6、Ligma7、Mafia8、Ok, Boomer 全删除属性dom破坏WW3 XSS GAME 地址&#xff1a;https://xss.pwnfunction.com/ 关卡难度层层递进&#xff0c;各个漏洞都有特点&#xff0c;值得…

【最大公约数和最小公倍数】求最大公约数和最小公倍数

输入两个正整数m和n&#xff0c;求其最大公约数和最小公倍数 使用C语言实现&#xff0c;具体代码&#xff1a; 使用辗转相除法&#xff08;也称欧几里得算法&#xff09;计算最大公约数 while(b ! 0){ temp a % b; a b; b temp; } 最小公倍数&#xff08;LCM&…

大模型高效微调工具 Hugging Face PEFT

概述 HF PEFT是一个为大型预训练模型提供高效微调方法的Python库。它通过采用训练少量提示参数或使用低秩适应等重新参数化方法&#xff0c;减少微调时训练参数的数量。本文主要介绍了PEFT库的内容、与Transformers的集成、核心知识点如AutoPeftModels、PeftConfig、PeftType和…

知识改变命运 数据结构【链表面试题】

1. 删除链表中等于给定值 val 的所有节点。 OJ链接 public ListNode removeElements(ListNode head, int val) {if (headnull) {return null;}ListNode curhead.next;ListNode prehead;while(cur!null) {if(cur.valval) {pre.nextcur.next;curcur.next;}else {precur;curcur.ne…

日拱一卒(5)——leetcode学习记录:股票购买

一、任务 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的…

【qt】跳转到另一个界面

如何在一个界面跳转到另一个界面呢&#xff1f; 1.具体步骤 1.先新建一个界面 2.选择qt设计师界面 3.选择W 4.新界面名称 5.界面设计 因为我们要实现通信&#xff0c;需要一个发送信息栏&#xff0c;一个发送按钮&#xff0c;一个清空发送栏按钮 6.实现跳转 我们可以参…

链表反转算法

链表的反转有较多的方法&#xff0c;如原地算法&#xff0c;迭代法、头插法、递归法&#xff0c;本文使用递归法和迭代法两种方式进行演示。 一、定义链表 typedef struct SinglyLinkNode {/**后继节点 */struct SinglyLinkNode* next;/** 节点数据域 */int data; } Lin…

海外代理IP网速快慢取决因素有哪些

在全球化日益加深的今天&#xff0c;海外代理IP成为许多用户进行跨境网络活动的重要工具。然而&#xff0c;用户在使用海外代理IP时&#xff0c;往往会遇到网速快慢不一的问题。本文将从多个角度探讨影响海外代理IP网速快慢的因素&#xff0c;帮助用户更好地理解并选择适合自己…

使用 prefetchComponents 进行组件预取

title: 使用 prefetchComponents 进行组件预取 date: 2024/8/17 updated: 2024/8/17 author: cmdragon excerpt: 摘要&#xff1a;本文介绍Nuxt.js中的prefetchComponents功能&#xff0c;用于预取组件以提高用户体验。通过在客户端后台下载和缓存组件&#xff0c;确保在用户…

普通人如何做文献阅读汇报?

最强小说推文——AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ 用AI啊&#xff01;以前啃个文献小半天&#xff0c;现在AI 2min搞定&#xff0c;从提取核心论点、参考文献到摘要、翻…

如何将 Windows 11/10/8/7 克隆到另一台计算机

为什么需要将 Windows克隆到新计算机 “我有一台新笔记本电脑来替换我的旧电脑&#xff0c;因为它运行几年后变得越来越慢。我现在面临的问题是如何让 Windows 10、程序和文件与旧 PC 保持相同。我不想重新安装 Windows 和应用程序。有没有快速简便的方法可以做到这一点&#…

检测到目标URL存在http host头攻击漏洞

漏洞描述 修复措施 方法一&#xff1a; nginx 的 default_server 指令可以定义默认的 server 去处理一些没有匹配到 server_name 的请求&#xff0c;如果没有显式定义&#xff0c;则会选取第一个定义的 server 作为 default_server。 server { …

数据结构——关于队列

1.队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出的特性 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为队头 2.队列的…

HiveSQL实战——大厂面试真题

一、字节跳动 最高峰同时直播人数 https://blog.csdn.net/SHWAITME/article/details/135918264 0 问题描述 有如下数据记录直播平台主播上播及下播时间&#xff0c;根据该数据计算出平台最高峰同时直播人数。 ------------------------------------------------------ | us…

NC 用两个栈实现队列

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 用两个栈来实…

计算最简比

原理 c 质数数组长度&#xff0c;除不了就c--&#xff0c;都除不了c0&#xff0c;while(0)退出循环。 mainwindow.h struct WbiH {int width;int height; };WbiH calcWbiH(int w, int h); mainwindow.cpp {......int width player->metaData(SLMD.at(i)).toSize().wi…

JVM上篇:内存与垃圾-回收篇05-本地方法接口和本地方法栈

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录 5. 本地方法接口和本地方法栈5.1. 什么是本地方法&#xff1f;5.2. 为什么使用 Native Method&#xff1f;5.2. 本地方法栈 5. 本地…

uniapp去掉页面导航条

在pages.json文件中&#xff0c;globalStyle中添加 ”app-plus“:{"titleNView":false }