【问题标题】:Having trouble ints from a program reading file从程序读取文件中遇到问题
【发布时间】:2017-10-07 04:55:47
【问题描述】:

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

程序#1:

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

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

do
{
printf("Please enter item data (part number, quanitity, price): ");
scanf("%d, %d, %f", &pnum, &quantity, &price);

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));


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

return 0;
}  

程序 #2:

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
{
fscanf(fp, "%d %d %f", &pnum, &quantity, &price);

printf("%5d", pnum);
printf("%9d", quantity);
printf("       $%.1f\n", price);

}while(pnum != 0);

return 0;
}

【问题讨论】:

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

标签: c string file int scanf


【解决方案1】:

其中一个关键问题是您在开始之前没有确定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;
}

给定输入文件:

123, 45, 56.78
234, 56, 67.89
333, 77, 88.88
0, 234, 100.92

它产生输出文件:

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;
}

对于相同的输入数据,它会产生输出:

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

您可以修改第二个程序,在对printf() 的一次调用中打印每行输出的所有数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2012-09-28
    • 2017-07-21
    • 1970-01-01
    相关资源
    最近更新 更多