gpt4 book ai didi

c - 使用命令行参数将数据从第二个 txt 文件传输到第二个字符数组时遇到问题

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

我遇到的确切问题是我们被分配创建一个具有 2 个命令行参数的程序,这两个参数都是文本文件。我的 arg[1] 代码工作正常,它读取文本文件并将其存储到数组中。一旦它被存储到名为 key 的数组中,它就会经历一个循环,只留下字母字符并将大写更改为小写。当我测试它并打印出名为 key 的最终数组时,这再次工作得很好。当我对 arg[2] 使用相同的代码时,第一个循环 (while(!feof(file2))) 甚至没有将其他文本文件的内容正确复制到名为 plain 的数组中。它复制所有内容,但在打印普通数组时在末尾添加▒,以测试在通过仅保留字母字符的循环运行之前是否包含所有字符。如果我在终端中输入文件时切换文件的顺序,则第二个文件可以正常使用 arg[1] 代码,但另一个文件则无法使用 arg[2] 代码。我使用的是 mobaxterm,所以我输入它就像“./a.out k1.txt p1.txt”,当然不带引号。我还注释掉了 arg[2] 中去除非字母字符的代码,只是为了尝试找出为什么 while 循环之前没有正确存储文件内容。

这是文本文件的内容

k1.txt(而不是空格,想象它进入下一行):

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

p1.txt:

“如果您发现自己几乎所有时间都花在理论上,请开始将注意力转向实际事物;这会改进您的理论。如果您发现自己几乎所有时间都花在实践上,请开始转向对理论事物的一些关注;这会提高你的实践。” - 唐纳德·高德纳

顺便说一句,这是一个加密分配,k1 是 key ,p1 是明文。

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

int main(int argc, char **argv) {

printf( "\ncommandline arguments including program name:\n\n");
int i;
for ( i = 0; i < argc; i++ ) {
printf( "argument %d: %s\n", i, argv[ i ] );
}
printf( "\n");

char* fname = argv[ 1 ];
FILE *file = fopen( fname, "r" );
char key[512];
int x,y, z=0;

if ( file == 0 )
{
printf( "Could not open file\n" );
} else {
printf( "File opened successfully\n" );

while(!feof(file))
{
fscanf(file, "%c", &key[z]);
z++;
}fscanf(file, "%c", &key[z]);

for(x=0; key[x] != '\0'; x++)
{
while(!((key[x] >= 'a' && key[x] <= 'z') || (key[x] >= 'A' && key[x] <= 'Z') || key[x] == '\0'))
{
for(y=x; key[y] != '\0'; ++y)
{
key[y]=key[y+1];
}
key[y] = '\0';
}
key[x] = tolower(key[x]);
}

printf("Key text:\n%s\n", key);
fclose( file );
}

char* fname2 = argv[ 2 ];
FILE *file2 = fopen( fname2, "r" );
char plain[512];
int j,k, l=0;


if ( file2 == 0)
{
printf("Could not open file\n");
}else {
printf("File opened successfully\n");

while(!feof(file2))
{
fscanf(file2, "%c", &plain[l]);
l++;
}fscanf(file2, "%c", &plain[l]);
/* for(j=0; key[j] != '\0'; j++)
{
while(!((plain[j] >= 'a' && plain[j] <= 'z') || (plain[j] >= 'A' && plain[j] <= 'Z') || plain[j] == '\0'))
{
for(k=j; plain[k] != '\0'; ++k)
{
plain[k]=plain[k+1];
}
plain[k] = '\0';
}
plain[j] = tolower(plain[j]);
}*/

printf("Plain text:\n%s\n", plain);
fclose(file2);
}


return 0;
}

最佳答案

<强> feof

Check end-of-file indicator Checks whether the end-of-File indicator associated with stream is set, returning a value different from zero if it is.

This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file.

Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point. [emphasis mine]

现在,让我们看看这个循环是如何工作的:

                      while(!feof(file))
{
fscanf(file, "%c", &key[z]);
z++;
}fscanf(file, "%c", &key[z]);

假设fscanf()已读取文件的最后一个字符。此后,流内部位置指示器指向 EOF,但 feof() 将返回 0,因为流上没有尝试读取操作,这将设置结束- 文件指示器。因此,控件进入循环,fscan() 将尝试从 file 读取。由于到达 EOF,fscan() 将设置文件结束指示符。现在EOF已设置,因此feof()将返回非零值并且循环将结束。因此,按照您使用 feof() 的方式,您将始终拥有 while 循环的额外迭代。
遇到 EOF 后,您仍在尝试从流 file 中读取:

fscanf(file, "%c", &key[z]);

这里,fscanf() 也将返回 EOF,因为没有任何内容可以从流 file 中读取。这种说法意义不大。

在 C 语言中,字符串实际上是一维字符数组,以空字符 \0 结尾。当您使用 %c 格式说明符从流中读取时,fscanf() 不会自动在末尾附加空字符。因此,字符数组 keyplain 在读取的字符末尾没有空字符,并且如果您尝试使用 %s 打印它们,您可能会在输出中得到一些垃圾字符。

你可以这样做:

while ((ret = fscanf(file, "%c", &key[z])) != EOF) {
z++;
}
key[z] = '\0';

您还可以使用 %s 格式说明符从 file 读取字符串,如下所示:

fscanf(file, "%511s", key);

使用 %s 格式说明符,您不需要循环,并且会在存储序列的末尾自动添加终止空字符。

最好添加对最大字符修饰符的检查,该修饰符比输入缓冲区的长度小 1(在您的情况下为 511)。

或者,您也可以使用 fgets() 从文件中读取。

<小时/>

检查一下:

while ( !feof (file) ) is always wrong?
Reading from file using fgets

关于c - 使用命令行参数将数据从第二个 txt 文件传输到第二个字符数组时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51006116/

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