strcmp 不比较来自 argv 的字符串
Strcmp not comparing strings from argv
** 26/10 更新 -> 首先感谢大家的帮助,我现在离我越来越近了,我需要更多的工作和学习,但我真的很感谢你们对我的帮助:-)
仍然不知道为什么 input.txt 文件中的第一个 "rain" 单词没有从 strcmp 获得正输出,并且从 cmd 我可以看到“<”括号不t 出现,除了最后一行,这是有效的行。
还检查了来自 Removing trailing newline character from fgets() input
的突出显示的回复
即使我将代码更改为以下内容:
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
/*
if ((pos = strchr(line, '\n')) != NULL)
*pos = '[=10=]';
*/
line[strcspn(line, "\n")] = 0;
我得到的结果与我使用 if 块的结果相同。也许我得到额外的 \0 可能是这种情况。任何人都有一个 link,我可以在其中阅读我刚刚使用的定界符,或者调试器的一个很好的参考,等等......我一来这里就会看一下?提前致谢!
read5.c 版本:现在从那个 input.txt 文件中,它在最后一个 "rain" 单词上有一个额外的 space,我删除了 space,并且它能够在 strcmp if 块中找到并获得最后一个单词作为真实结果的比较,运行ning。但这是唯一一个来自 if 块的真正肯定结果的字符串。
在cmd上我可以看到:
$./read5 input.txt rain output.txt sun
>Maria
>rain
>manel
>Bla bla
<rain>
Found it! rain
在 output.txt 上变为:
Maria
rain
manel
Bla bla
sun
read5.c
#include <stdio.h>
#include <string.h>
/**
* Compile program:
* gcc read3.c -o read3
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read3 input.txt compare outout.txt replace\"\n\n");
}
/* opening file for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1; //TODO check if: return 1 because it was expected, right?
}
replace = argv[4];
/*
printf(); made to test version 2
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
*/
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
if ((pos = strchr(line, '\n')) != NULL)
*pos = '[=13=]';
/* print str enclosed in <> so we can see what str actually contains */
//printf("Inside the loop, got the string: %s\n", line);
//printing the strings with defined delimiters
printf("<%s>\n", line);
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
没有编辑的第一个问题:25/10
我需要制作一个 运行 的程序,如下所示:
./read2 input.txt rain output.txt sun
它读取 input.txt
,搜索 rain
字符串,如果找到它,将其替换为 sun
字符串并输出 input.txt
中的所有文本和替换到 output.txt
。
但是根据我目前的代码,strcmp
没有比较我想要的字符串,也许它有我在命令行上获得的额外 space,我不知道不知道...现在正在做的是复制从 input.txt
到 output.txt
的所有内容...它总是 运行 宁 else
块...
Read2.c:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char str[60];
//char* token;
/* opening file for reading */
fp = fopen(argv[1], "r");
char *compare = argv[2];
fo = fopen(argv[3], "w+");
char *replace = argv[4];
if (fp == NULL) {
perror("Error opening file");
return(-1);
}
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
while (fgets(str, 60, fp) != NULL) {
/* writing content to stdout */
//Take the \n out
//token = strtok(str, "\n");
printf("Inside the loop, got the string: %s\n", str);
if (strcmp(compare, str) == 0) {
//puts(str);
printf("Found it! %s \n", str);
fprintf(fo, "%s", replace);
} else {
fprintf(fo, "%s", str);
}
}
fclose(fp);
return(0);
}
input.txt:
Maria
rain
manel
Bla bla
rain
Ouput.txt 变得与 input.txt 完全一样,并且在它为空之前,所以代码可以正常工作,除了使用 strcmp
.
测试的 if 块
问题出在 str
缓冲区末尾的 \n
。 fgets
在它读取的行的末尾添加 \n
,你需要在比较之前去掉它。
这就是你需要的:
while (fgets(str, 60, fp) != NULL) {
/* remove \n from at the end of the str buffer*/
char *pos;
if ((pos = strchr(str, '\n')) != NULL)
*pos = '[=10=]';
/* print str enclosed in <> so we can see what str actually contains */
printf("Inside the loop, got the string: <%s>\n", str);
if (strcmp(compare, str) == 0) {
printf("Found it! %s\n", str);
fprintf(fo, "%s\n", replace);
}
else {
fprintf(fo, "%s\n", str);
}
}
查看代码中的注释进行解释。
您的方法失败了,因为从输入文件中读取的行包含尾随换行符 '\n'
,这使得比较 return 非零。
您可以在与搜索字符串比较之前去掉换行符。
注意还有其他问题:
- 您应该通过测试
argc > 4
. 验证是否传递了足够的命令行参数
- 无需以更新模式打开输出文件
"w+"
,"w"
更简单更好
- 60 字节对于线阵列来说有点小,将正确处理的最长线限制为 58 字节。
这是一个改进的版本:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[256];
if (argc <= 4) {
printf("missing command line arguments\n");
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if (fo == NULL) {
perror("Error opening output file");
return 1;
}
replace = argv[4];
while (fgets(line, sizeof line, fp) != NULL) {
line[strcspn(line, "\n")] = '[=10=]';
if (strcmp(line, compare) == 0) {
printf("fount it!);
fprintf(fo, "%s\n", replace);
} else {
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
请注意,长行将被分成适合 line
数组的块,因此上述幼稚的方法可能会出现误报。
您可以使用此内部循环完全消除此限制:
int c;
int pos = 0;
int cmplen = strlen(compare);
for (;;) {
c = getc(fp);
if (c == '\n' || c == EOF) {
if (pos == cmplen) {
fprintf(fo, "%s", replace);
} else
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = 0;
if (c == EOF)
break;
} else {
if (pos >= 0) {
if (compare[pos] == (char)c) {
pos++;
continue;
}
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = -1;
}
}
putc(c, fo);
}
来自 man fgets
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed
to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A
terminating null byte ('[=13=]') is stored after the last character in the buffer.
因此您需要从缓冲区 s
中删除换行符,例如:
c[strlen(c) - 1] = 0 when c[strlen(c) - 1] == '\n'
read.c
#include <stdio.h>
#include <string.h>
/**
* How to compile program:
* gcc read.c -o read
*
* How to run the program:
* .> ./read input.txt rainy output.txt sunny
* (On Windows MinGW compiler, simply:
* .> read input.txt rainy output.txt sunny - without ./)
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read input.txt compare outout.txt replace\"\n\n");
}
/* Opening files for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1;
}
replace = argv[4];
while( fgets (line, (sizeof line), fp)!=NULL ) {
line[strcspn(line, "\n")] = 0;
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
/*
Important info
strcspn ::
Locate first occurrence of character in string,
after locating the first occurrence of \n, replaces it by 0.
Sources::
Used to debug:
.>printf("1st: Reads input.txt, removes '\n' from fgets, and prints it \n");
.>printf("2nd: Compares each line with 'rainy' \n");
.>printf("<%s>\n", line);
*/
input.txt
cloudy
rainy
chilly
rainy
rainy
** 26/10 更新 -> 首先感谢大家的帮助,我现在离我越来越近了,我需要更多的工作和学习,但我真的很感谢你们对我的帮助:-)
仍然不知道为什么 input.txt 文件中的第一个 "rain" 单词没有从 strcmp 获得正输出,并且从 cmd 我可以看到“<”括号不t 出现,除了最后一行,这是有效的行。
还检查了来自 Removing trailing newline character from fgets() input
的突出显示的回复即使我将代码更改为以下内容:
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
/*
if ((pos = strchr(line, '\n')) != NULL)
*pos = '[=10=]';
*/
line[strcspn(line, "\n")] = 0;
我得到的结果与我使用 if 块的结果相同。也许我得到额外的 \0 可能是这种情况。任何人都有一个 link,我可以在其中阅读我刚刚使用的定界符,或者调试器的一个很好的参考,等等......我一来这里就会看一下?提前致谢!
read5.c 版本:现在从那个 input.txt 文件中,它在最后一个 "rain" 单词上有一个额外的 space,我删除了 space,并且它能够在 strcmp if 块中找到并获得最后一个单词作为真实结果的比较,运行ning。但这是唯一一个来自 if 块的真正肯定结果的字符串。
在cmd上我可以看到:
$./read5 input.txt rain output.txt sun
>Maria
>rain
>manel
>Bla bla
<rain>
Found it! rain
在 output.txt 上变为:
Maria
rain
manel
Bla bla
sun
read5.c
#include <stdio.h>
#include <string.h>
/**
* Compile program:
* gcc read3.c -o read3
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read3 input.txt compare outout.txt replace\"\n\n");
}
/* opening file for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1; //TODO check if: return 1 because it was expected, right?
}
replace = argv[4];
/*
printf(); made to test version 2
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
*/
while( fgets (line, sizeof line, fp)!=NULL ) {
/* remove \n from at the end of the str buffer*/
char * pos;
if ((pos = strchr(line, '\n')) != NULL)
*pos = '[=13=]';
/* print str enclosed in <> so we can see what str actually contains */
//printf("Inside the loop, got the string: %s\n", line);
//printing the strings with defined delimiters
printf("<%s>\n", line);
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
没有编辑的第一个问题:25/10
我需要制作一个 运行 的程序,如下所示:
./read2 input.txt rain output.txt sun
它读取 input.txt
,搜索 rain
字符串,如果找到它,将其替换为 sun
字符串并输出 input.txt
中的所有文本和替换到 output.txt
。
但是根据我目前的代码,strcmp
没有比较我想要的字符串,也许它有我在命令行上获得的额外 space,我不知道不知道...现在正在做的是复制从 input.txt
到 output.txt
的所有内容...它总是 运行 宁 else
块...
Read2.c:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char str[60];
//char* token;
/* opening file for reading */
fp = fopen(argv[1], "r");
char *compare = argv[2];
fo = fopen(argv[3], "w+");
char *replace = argv[4];
if (fp == NULL) {
perror("Error opening file");
return(-1);
}
//printf("We are going to compare %s\n", compare);
//printf("We are going to replace it with %s\n", replace);
while (fgets(str, 60, fp) != NULL) {
/* writing content to stdout */
//Take the \n out
//token = strtok(str, "\n");
printf("Inside the loop, got the string: %s\n", str);
if (strcmp(compare, str) == 0) {
//puts(str);
printf("Found it! %s \n", str);
fprintf(fo, "%s", replace);
} else {
fprintf(fo, "%s", str);
}
}
fclose(fp);
return(0);
}
input.txt:
Maria
rain
manel
Bla bla
rain
Ouput.txt 变得与 input.txt 完全一样,并且在它为空之前,所以代码可以正常工作,除了使用 strcmp
.
问题出在 str
缓冲区末尾的 \n
。 fgets
在它读取的行的末尾添加 \n
,你需要在比较之前去掉它。
这就是你需要的:
while (fgets(str, 60, fp) != NULL) {
/* remove \n from at the end of the str buffer*/
char *pos;
if ((pos = strchr(str, '\n')) != NULL)
*pos = '[=10=]';
/* print str enclosed in <> so we can see what str actually contains */
printf("Inside the loop, got the string: <%s>\n", str);
if (strcmp(compare, str) == 0) {
printf("Found it! %s\n", str);
fprintf(fo, "%s\n", replace);
}
else {
fprintf(fo, "%s\n", str);
}
}
查看代码中的注释进行解释。
您的方法失败了,因为从输入文件中读取的行包含尾随换行符 '\n'
,这使得比较 return 非零。
您可以在与搜索字符串比较之前去掉换行符。
注意还有其他问题:
- 您应该通过测试
argc > 4
. 验证是否传递了足够的命令行参数
- 无需以更新模式打开输出文件
"w+"
,"w"
更简单更好 - 60 字节对于线阵列来说有点小,将正确处理的最长线限制为 58 字节。
这是一个改进的版本:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[256];
if (argc <= 4) {
printf("missing command line arguments\n");
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if (fo == NULL) {
perror("Error opening output file");
return 1;
}
replace = argv[4];
while (fgets(line, sizeof line, fp) != NULL) {
line[strcspn(line, "\n")] = '[=10=]';
if (strcmp(line, compare) == 0) {
printf("fount it!);
fprintf(fo, "%s\n", replace);
} else {
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
请注意,长行将被分成适合 line
数组的块,因此上述幼稚的方法可能会出现误报。
您可以使用此内部循环完全消除此限制:
int c;
int pos = 0;
int cmplen = strlen(compare);
for (;;) {
c = getc(fp);
if (c == '\n' || c == EOF) {
if (pos == cmplen) {
fprintf(fo, "%s", replace);
} else
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = 0;
if (c == EOF)
break;
} else {
if (pos >= 0) {
if (compare[pos] == (char)c) {
pos++;
continue;
}
if (pos > 0) {
fprintf(fo, "%*s", pos, compare);
}
pos = -1;
}
}
putc(c, fo);
}
来自 man fgets
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('[=13=]') is stored after the last character in the buffer.
因此您需要从缓冲区 s
中删除换行符,例如:
c[strlen(c) - 1] = 0 when c[strlen(c) - 1] == '\n'
read.c
#include <stdio.h>
#include <string.h>
/**
* How to compile program:
* gcc read.c -o read
*
* How to run the program:
* .> ./read input.txt rainy output.txt sunny
* (On Windows MinGW compiler, simply:
* .> read input.txt rainy output.txt sunny - without ./)
*
*/
int main (int argc, char **argv) {
FILE *fp, *fo;
char *compare, *replace;
char line[246];
if (argc <= 4){
printf(">Missing arguments on the command line.\n");
printf(">Be sure you run the program as\n\"./read input.txt compare outout.txt replace\"\n\n");
}
/* Opening files for reading */
fp = fopen(argv[1] , "r");
if(fp == NULL){
perror("Error opening input file");
return 1;
}
compare = argv[2];
fo = fopen(argv[3], "w");
if(fo == NULL){
perror("Error opening output file");
return 1;
}
replace = argv[4];
while( fgets (line, (sizeof line), fp)!=NULL ) {
line[strcspn(line, "\n")] = 0;
if(strcmp(compare, line) == 0){
printf("Found it! %s \n", line);
fprintf(fo, "%s\n", replace);
}
else{
fprintf(fo, "%s\n", line);
}
}
fclose(fp);
fclose(fo);
return 0;
}
/*
Important info
strcspn ::
Locate first occurrence of character in string,
after locating the first occurrence of \n, replaces it by 0.
Sources::
Used to debug:
.>printf("1st: Reads input.txt, removes '\n' from fgets, and prints it \n");
.>printf("2nd: Compares each line with 'rainy' \n");
.>printf("<%s>\n", line);
*/
input.txt
cloudy
rainy
chilly
rainy
rainy