gpt4 book ai didi

c - 在 C 中附加输出文件

转载 作者:行者123 更新时间:2023-11-30 14:21:30 24 4
gpt4 key购买 nike

我正在解决 USACO 上的问题。在这个问题中,我必须以两个字符串作为输入并计算以 47 为模的数值。如果值相同,则要打印 GO,否则必须打印 STAY。初始数值将通过字母数值的乘积计算(A 为 1,Z 为 26),然后通过取模计算最终数字。

我的程序正在编译,没有任何错误,第一个案例也成功了。但问题出在第二种情况以及我的文件的附加方式。程序如下:-

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define MAX 6
main()
{
int cal(char *ptr);
int a,b;
char *comet,*group;
FILE *fptr;
comet=malloc(6*sizeof(char));
group=malloc(6*sizeof(char));
scanf("%s",comet);
a=cal(comet);
scanf("%s",group);
b=cal(group);
fptr=fopen("ride.out","a+"); (1)
//fptr=fopen("ride.txt","a+"); (2)
if(a==b)
fprintf(fptr,"GO\n"); (3)
//printf("GO\n"); (4)
else
fprintf(fptr,"STAY\n"); (5)
//printf("STAY\n"); (6)
fclose(fptr);
return 0;
}
int cal(char *ptr)
{
int c,prod=1,mod;
while(*ptr)
{
c=(*ptr++)-'A'+1;
prod=prod*c;
}
mod=prod%47;
return mod;
}

输出:-

output_image

第一种情况是设置两个字符串:-

    COMETQ
    HVNGAT

第二种情况在错误通知本身中给出。

如果我从 (2) 中删除注释符号并将其放在 (1) 上,那么程序就可以正常工作,因为我可以看到文件的内容,并且它们的显示方式正如评分系统想要的那样。 (1) 的实际陈述并没有发生这种情况。第(4)行和(6)行的注释也很好,但第(1)行不行。我无法弄清楚这一点。有什么帮助吗?

最佳答案

首先一些注意事项:

  • main() :体面的主要是:

    int main(void)
    or
    int main(int argc, char *argv[])
  • 使用 malloc()您应该始终检查它是否返回 NULL ,又名失败或失败。

  • 始终free() malloc 的对象。
  • 每个人都有他/她自己的编码风格。我找到了this to be invaluable当谈到C编码时。使用它作为许多其他人的基础。重点是结构化代码更容易阅读、调试、解码等。
<小时/>

有关代码的更多详细信息:

cal()签名

main 中的第一行您声明 cal() 的签名。尽管这有效,您可能会将其放在 main 之上,或输入 cal()以上功能完整main .

最大长度

您有一个定义 #define MAX 6你从不使用的。如果最多有六个字符并且您读取了一个字符串,则还必须考虑尾随零。

例如来自cplusplus.com scanf :

specifier 's': Any number of non-whitespace characters, stopping at the first whitespace character found. A terminating null character is automatically added at the end of the stored sequence.

因此:

#define MAX_LEN_NAME    7
...
comet = malloc(sizeof(char) * MAX_LEN_NAME);

学习使用malloc()很好。在这里这样做并没有什么错误但是因为它很简单,您可能会想使用:

char comet[MAX_LEN_NAME] = {0};
char group[MAX_LEN_NAME] = {0};

相反。至少:如果使用malloc然后检查是否成功并在完成后释放,否则使用静态数组。

更安全的 scanf()

scanf()给定"%s"不会停止读取目标缓冲区的大小 - 它继续读取数据并将其写入内存中的连续地址,直到读取到空白。例如:

/* data stream = "USACOeRRORbLAHbLAH NOP" */
comet = malloc(szieof(char) * 7);
scanf("%s", buf);

在内存中我们会:

Address (example)
0x00000f comet[0]
0x000010 comet[1]
0x000011 comet[2]
0x000012 comet[3]
0x000013 comet[4]
0x000014 comet[5]
0x000015 comet[6]
0x000016 comet[7]
0x000017 /* Anything; Here e.g. group starts, or perhaps fptr */
0x000018 /* Anything; */
0x000019 /* Anything; */
...

当阅读上面建议的流/字符串时,我们不会读 USACOe进入comet但我们会继续阅读超出 comet 的范围。换句话说(可能)覆盖其他变量等。这可能听起来很愚蠢,但由于 C 是一种低级语言,这是您必须了解的事情之一。随着您了解更多,您很可能也会爱上它的力量:)

为了防止这种情况,您可以通过例如限制读取使用maximum length + [what to read] 。例如:

 scanf("%6[A-Z]", comet);
| | |
| | +------- Write to `comet`
| +-------------- Read only A to Z
+---------------- Read maximum 6 entities

输入数据

阅读您的预期结果、您的错误、您的(N)评论等。听起来您应该有一个输入文件和一个输出文件。

正如您的代码现在一样,它依赖于从标准输入读取数据,又名 stdin 。因此您还可以使用 scanf() 。我怀疑你应该read from file with fscanf()相反。

所以:类似:

FILE *fptr_in;
char *file_data = "ride.in";
int res;
...
if ((fptr_in = fopen(file_data, "r")) == NULL) {
fprintf(stderr, "Unable to open %s for reading.\n", file_data);
return 1; /* error code returned by program */
}
if ((res = fscanf(fptr_in, "%6[A-Z]%*[ \n]", comet)) != 1) {
fprintf(stderr, "Read comet failed. Got %d.\n", res);
return 2;
}

b = cal(comet);

if ((res = fscanf(fptr_in, "%6[A-Z]%*[ \n]", group)) != 1) {
fprintf(stderr, "Read group failed. Got %d.\n", res);
return 2;
}

...

cal() 函数

首先,命名。假设这是一个项目的开始,最终会产生多个文件和数千行代码。您可能没有名为 cal() 的函数。学会给函数起个好听的名字。上面关于编码风格的链接给出了一些要点。恕我直言,在小型项目中也这样做。这是一个很好的练习,可以让你在写大字的时候变得更容易。命名它例如cprod_mod_47() .

然后是mod变量(可能还有 c)是多余的。另一种选择可能是:

int cprod_mod_47(char *str)
{
int prod = 1;

while (*str)
prod *= *(str++) - 'A' + 1;

return prod % 47;
}
<小时/>

一些更一般的建议

编译时使用许多警告和错误选项。例如。如果使用 gcc 说:

$ gcc -Wall -Wextra -pedantic -std=c89 -o my_prog my_prog.c

这是巨大的帮助。进一步是使用像valgrind这样的工具和gdb无价之宝。

关于c - 在 C 中附加输出文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14661859/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com