C 从程序读取文件时遇到问题

C 从程序读取文件时遇到问题,c,string,file,int,scanf,C,String,File,Int,Scanf,我正在做一个自我项目,我试图学习如何编写和创建文件。有两个问题。第一个程序应该将信息写入一个文件,当用户给出的整数复制到文件中时,该文件也会在其创建的txt文件中给出难以辨认的字符。第二个问题是,当我编译程序#2时,它不会显示从txt文件输入的信息。(旁注:我使用的libs是string、stdlib、stdio)这个程序是用C编写的 计划#1: 计划#2: 其中一个关键问题是,在开始之前不能确保str是空字符串,因此不知道输出开头是什么垃圾。另一种方法是,您将整个str加上一个不属于str的字

我正在做一个自我项目,我试图学习如何编写和创建文件。有两个问题。第一个程序应该将信息写入一个文件,当用户给出的整数复制到文件中时,该文件也会在其创建的txt文件中给出难以辨认的字符。第二个问题是,当我编译程序#2时,它不会显示从txt文件输入的信息。(旁注:我使用的libs是string、stdlib、stdio)这个程序是用C编写的

计划#1:

计划#2:


其中一个关键问题是,在开始之前不能确保
str
是空字符串,因此不知道输出开头是什么垃圾。另一种方法是,您将整个
str
加上一个不属于
str
的字节写入文件,而实际上您只需要写入格式化数据。由于练习需要
fwrite()
,因此代码可以继续使用该选项

你应该检查输入;你应该检查文件是否打开;您应该避免缓冲区溢出

这是第一个程序的第一个过程:

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

int main(void)
{
    FILE *fp;
    int pnum, quantity;
    float price;
    char num1[20];
    char num2[20];
    char num3[20];
    char str[100] = "";

    printf("This program stores a business inventory.\n");
    fp = fopen("inventory.txt", "w");

    do
    {
        printf("Please enter item data (part number, quantity, price): ");
        if (scanf("%d, %d, %f", &pnum, &quantity, &price) != 3)
        {
            pnum = 0;
            quantity = 0;
            price = 0.0;
        }

        sprintf(num1, "%d", pnum);
        sprintf(num2, "%d", quantity);
        sprintf(num3, "%.1f", price);

        strcat(str, num1);
        strcat(str, " ");
        if (pnum != 0)
        {
            strcat(str, num2);
            strcat(str, " ");
            strcat(str, num3);
            strcat(str, " ");
        }
        else
        {
            strcat(str, num1);
            strcat(str, " ");
            strcat(str, num1);
            strcat(str, " ");
            strcat(str, num1);
            strcat(str, " ");
        }
    } while (pnum != 0 && strlen(str) < sizeof(str) - 20);

    fwrite(str, 1, sizeof(str) + 1, fp);
    fclose(fp);
    printf("Thank you. Inventory stored in file inventory.txt.\n");

    return 0;
}
它生成输出文件:

0x0000: 31 32 33 20 34 35 20 35 36 2E 38 20 32 33 34 20   123 45 56.8 234 
0x0010: 35 36 20 36 37 2E 39 20 33 33 33 20 37 37 20 38   56 67.9 333 77 8
0x0020: 38 2E 39 20 30 20 30 20 30 20 30 20 00 00 00 00   8.9 0 0 0 0 ....
0x0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
* (2)
0x0060: 00 00 00 00 01                                    .....
0x0065:
注意所有尾随的空字节

第二步通过使用
snprintf()
格式化行,然后使用
fwrite()
写入行,从而简化了代码-尽管只使用
fprintf()
格式化和写入非常诱人

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

int main(void)
{
    const char filename[] = "inventory.txt";
    FILE *fp = fopen(filename, "w");

    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file %s for writing\n", filename);
        return 1;
    }
    printf("This program stores a business inventory.\n");

    int pnum, quantity;
    float price;
    do
    {
        printf("Please enter item data (part number, quantity, price): ");
        if (scanf("%d, %d, %f", &pnum, &quantity, &price) != 3 || pnum == 0)
        {
            pnum = 0;
            quantity = 0;
            price = 0.0;
        }
        char str[100];
        snprintf(str, sizeof(str), "%d %d %.2f\n", pnum, quantity, price);
        if (fwrite(str, sizeof(char), strlen(str), fp) != strlen(str))
            break;
    } while (pnum != 0);

    fclose(fp);
    printf("Thank you. Inventory stored in file %s\n", filename);

    return 0;
}
或者,作为普通文本:

123 45 56.78
234 56 67.89
333 77 88.88
0 0 0.00
注意,文件中根本没有空字节

轻度修订的reader程序如下所示:

#include <stdio.h>

int main(void)
{
    FILE *fp;
    int pnum, quantity;
    float price;

    printf("Below are the items in your inventory\n");

    printf("Part# Quantity Item Price\n");

    fp = fopen("inventory.txt", "r");
    //rewind(fp);
    do
    {
        if (fscanf(fp, "%d %d %f", &pnum, &quantity, &price) != 3)
            break;

        printf("%5d", pnum);
        printf("%9d", quantity);
        printf("       $%.1f\n", price);
    } while (pnum != 0);

    printf("All data read\n");

    return 0;
}

您可以修改第二个程序,在一次调用
printf()

中打印每行输出的所有数据。您需要找到一个以可读格式转储文件字节的工具,例如
xxd
od-c
或其他类似程序。将其应用于您的文件。我相信您会发现文件中有空字节,这将扰乱读取过程。您使用了太多的
strcat()
操作;您应该使用
sprintf()
在一次调用中创建整个字符串。您必须在读取代码中检查从
fscanf()
返回的值-它可能读取第一批数据;由于空字节,它可能不会再读取了。有没有可能获得一个示例,说明如何使用sprintf()和3个给定的整数,以便在一次调用中创建整个字符串?此外,用户还可以多次输入pnum、数量、价格。sprintf()会添加到该字符串上吗?
snprintf(str,sizeof(str),%d%d%f\n),pnum,数量,价格)就可以了。我误读了部分代码(空字节问题并没有以我认为的形式出现),但是您有一些未定义的行为。在执行
strcat()
操作之前,需要在字符串的开头放置一个空字节-否则,您不知道要从哪里开始复制数据。写入的字节数不应超过
str
中的字节数。您应该检查字符串溢出。您还需要检查输入
scanf()
。需要检查所有输入。请注意,
snprintf()
返回它写入或将写入字符串的字符数。您可以使用它来进行连接。如何将空字节放在字符串的开头?这会修复txt文件中未定义的行为吗?还有,我只是想澄清一下。snprintf函数是否应该替换我写入程序的strcat?
#include <assert.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    const char filename[] = "inventory.txt";
    FILE *fp = fopen(filename, "w");

    if (fp == NULL)
    {
        fprintf(stderr, "Failed to open file %s for writing\n", filename);
        return 1;
    }
    printf("This program stores a business inventory.\n");

    int pnum, quantity;
    float price;
    do
    {
        printf("Please enter item data (part number, quantity, price): ");
        if (scanf("%d, %d, %f", &pnum, &quantity, &price) != 3 || pnum == 0)
        {
            pnum = 0;
            quantity = 0;
            price = 0.0;
        }
        char str[100];
        snprintf(str, sizeof(str), "%d %d %.2f\n", pnum, quantity, price);
        if (fwrite(str, sizeof(char), strlen(str), fp) != strlen(str))
            break;
    } while (pnum != 0);

    fclose(fp);
    printf("Thank you. Inventory stored in file %s\n", filename);

    return 0;
}
0x0000: 31 32 33 20 34 35 20 35 36 2E 37 38 0A 32 33 34   123 45 56.78.234
0x0010: 20 35 36 20 36 37 2E 38 39 0A 33 33 33 20 37 37    56 67.89.333 77
0x0020: 20 38 38 2E 38 38 0A 30 20 30 20 30 2E 30 30 0A    88.88.0 0 0.00.
0x0030:
123 45 56.78
234 56 67.89
333 77 88.88
0 0 0.00
#include <stdio.h>

int main(void)
{
    FILE *fp;
    int pnum, quantity;
    float price;

    printf("Below are the items in your inventory\n");

    printf("Part# Quantity Item Price\n");

    fp = fopen("inventory.txt", "r");
    //rewind(fp);
    do
    {
        if (fscanf(fp, "%d %d %f", &pnum, &quantity, &price) != 3)
            break;

        printf("%5d", pnum);
        printf("%9d", quantity);
        printf("       $%.1f\n", price);
    } while (pnum != 0);

    printf("All data read\n");

    return 0;
}
Below are the items in your inventory
Part# Quantity Item Price
  123       45       $56.8
  234       56       $67.9
  333       77       $88.9
    0        0       $0.0
All data read