strcmp说看似相同的字符串并不相等

strcmp说看似相同的字符串并不相等,c,strcmp,C,Strcmp,我正在使用strcmp比较两个字符串lhs通过fgets来自文件流rhs是由for循环生成的一个n-1空格序列 例子 #包括 #包括 int main(){ 尺寸n=10; char-rhs[n]; memset(rhs',n-1);//使用memset()填充空格 rhs[n-1]=0;//添加NUL终止符 printf(“len=%zu\n”,strlen(rhs)); char-lhs[n]; FILE*FILE=fopen(“测试”、“r”); fgets(lhs、sizeof(lhs

我正在使用strcmp比较两个字符串
lhs
通过
fgets
来自文件流
rhs
是由for循环生成的一个
n-1
空格序列


例子
#包括
#包括
int main(){
尺寸n=10;
char-rhs[n];
memset(rhs',n-1);//使用memset()填充空格
rhs[n-1]=0;//添加NUL终止符
printf(“len=%zu\n”,strlen(rhs));
char-lhs[n];
FILE*FILE=fopen(“测试”、“r”);
fgets(lhs、sizeof(lhs)、文件);
printf(“读取=%s\n”,lhs);
返回0;
}

当使用gdb时,我会发现我有两个看起来相同的字符串(我为此使用了gdb的
print
):

lhs
=

rhs
=

然而,
strcmp(左、右)!=0
。这应该返回一个
0
,指示字符串是相同的,但是我得到了一些其他非零值


为什么这些字符串不相等?

输入缓冲区的字符串不完全相同,您忽略添加空终止符意味着字符串程序将继续将字符串读取到缓冲区中,直到找到空终止符为止,运行以下代码向我们展示了这一点:

size_t n = 5;
char lhs[n];
char rhs[n];
for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
for(int i = 0; rhs[i]; i++)
    printf("| %d ", rhs[i]);
size\u t n=5;
char-lhs[n];
char-rhs[n];
对于(int i=0;i
输出:

|32 | 32 | 32 | 32 | 32 |未知值…,可以是0,但在此之前仍然是数组的一部分

您应该将数组视为内存地址,尤其是将其传递给函数时

你应该这样写:

for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
rhs[n-1] = '\x00'; // null terminator
#include <string.h>
#include <stdio.h>

int main() {
  size_t n = 10;
  char rhs[n];

  memset(rhs, ' ', n - 1); // Fill with spaces using memset()
  rhs[n-1] = 0; // Add NUL terminator

  printf("len=%zu\n", strlen(rhs));

  char lhs[n];

  FILE* file = fopen("test", "r");
  fgets(lhs, sizeof(lhs), file);
  printf("read=%s\n", lhs);

  return 0;
}
for(int i=0;i
输入缓冲区的字符串不完全相同,您忽略添加空终止符意味着字符串程序将继续将字符串读入缓冲区,直到找到空终止符为止,运行以下代码向我们展示了这一点:

size_t n = 5;
char lhs[n];
char rhs[n];
for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
for(int i = 0; rhs[i]; i++)
    printf("| %d ", rhs[i]);
size\u t n=5;
char-lhs[n];
char-rhs[n];
对于(int i=0;i
输出:

|32 | 32 | 32 | 32 | 32 |未知值…,可以是0,但在此之前仍然是数组的一部分

您应该将数组视为内存地址,尤其是将其传递给函数时

你应该这样写:

for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
rhs[n-1] = '\x00'; // null terminator
#include <string.h>
#include <stdio.h>

int main() {
  size_t n = 10;
  char rhs[n];

  memset(rhs, ' ', n - 1); // Fill with spaces using memset()
  rhs[n-1] = 0; // Add NUL terminator

  printf("len=%zu\n", strlen(rhs));

  char lhs[n];

  FILE* file = fopen("test", "r");
  fgets(lhs, sizeof(lhs), file);
  printf("read=%s\n", lhs);

  return 0;
}
for(int i=0;i
清理了此代码,创建了一个完整的最小示例,如下所示:

for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
rhs[n-1] = '\x00'; // null terminator
#include <string.h>
#include <stdio.h>

int main() {
  size_t n = 10;
  char rhs[n];

  memset(rhs, ' ', n - 1); // Fill with spaces using memset()
  rhs[n-1] = 0; // Add NUL terminator

  printf("len=%zu\n", strlen(rhs));

  char lhs[n];

  FILE* file = fopen("test", "r");
  fgets(lhs, sizeof(lhs), file);
  printf("read=%s\n", lhs);

  return 0;
}
#包括
#包括
int main(){
尺寸n=10;
char-rhs[n];
memset(rhs',n-1);//使用memset()填充空格
rhs[n-1]=0;//添加NUL终止符
printf(“len=%zu\n”,strlen(rhs));
char-lhs[n];
FILE*FILE=fopen(“测试”、“r”);
fgets(lhs、sizeof(lhs)、文件);
printf(“读取=%s\n”,lhs);
返回0;
}

在这里,重要的是不要从
fgets
分配,如果已打开
-Wall
,则这是一个警告。

清理此代码以创建一个完整的最小示例,如下所示:

for(int i = 0; i < n-1; i++)
    rhs[i] = ' ';
rhs[n-1] = '\x00'; // null terminator
#include <string.h>
#include <stdio.h>

int main() {
  size_t n = 10;
  char rhs[n];

  memset(rhs, ' ', n - 1); // Fill with spaces using memset()
  rhs[n-1] = 0; // Add NUL terminator

  printf("len=%zu\n", strlen(rhs));

  char lhs[n];

  FILE* file = fopen("test", "r");
  fgets(lhs, sizeof(lhs), file);
  printf("read=%s\n", lhs);

  return 0;
}
#包括
#包括
int main(){
尺寸n=10;
char-rhs[n];
memset(rhs',n-1);//使用memset()填充空格
rhs[n-1]=0;//添加NUL终止符
printf(“len=%zu\n”,strlen(rhs));
char-lhs[n];
FILE*FILE=fopen(“测试”、“r”);
fgets(lhs、sizeof(lhs)、文件);
printf(“读取=%s\n”,lhs);
返回0;
}

在这里,重要的是不要从
fgets
分配,如果打开了
-Wall
,这是一个警告。

打印出
lhs
rhs
的每个
char
,直到
n-1
char,并查看它们之间的不同。顺便说一句,你说
lhs
是由
fgets
读取的,但是你的伪代码显示正在读取
rhs
。您应该显示真实代码,而不是伪代码。
rhs
的大小是
n-1
,但您尝试将
n
字节读入其中。不太好。如果在它读取的行上有一个换行符,那么
null
终止符在哪里?
fgets()
也会留下尾随的换行符。如何查看字符串内容?请注意,
fgets
保留了比较前必须删除的换行符。打印出
lhs
rhs
的每个
char
,直到
n-1
char,并查看它们之间的不同之处。顺便说一句,你说
lhs
是由
fgets
读取的,但是你的伪代码显示正在读取
rhs
。您应该显示真实代码,而不是伪代码。
rhs
的大小是
n-1
,但您尝试将
n
字节读入其中。不太好。如果在它读取的行上有一个换行符,那么
null
终止符在哪里?
fgets()
也会留下尾随的换行符。如何查看字符串内容?请注意,
fgets
保留了比较前必须删除的换行符。感谢您的清理。现在我终于明白了一个真正完整的、最小的例子是什么样子了。正如其他人所建议的,缺少空终止符是我的问题。谢谢你的清理。现在我终于明白了一个真正完整的、最小的例子是什么样子了。正如其他人所说,缺少空终止符是我的问题。