我写了一个小程序作为示例来复制我遇到的问题。该程序以这种方式使用并操纵两行代码:
' '
),然后是一个数字。'\0'
。这是最小的程序:
#include <stdio.h>
#include <string.h>
void read(char *text)
{
// create and initialize the line holder
int k = 0;
char line[10];
line[0] = '\0';
for (int i = 0;text[i] != '\0';i++)
{
if (text[i] == '\n')
{
// k now points to the character right after the last assigned one, so put 0 in that place
line[k] = '\0';
// initialize data objects that will hold text and number
char letters[5];
letters[0] = '\0';
char val;
// step through the line, and stop if you 1. reached a blank or 2. reached the end of a line
int j = 0;
while (line[j] != ' ' && line[j] != '\t' && j <= (strlen(line) - 1))
{
printf("%d <= %ld = %d\n", j, strlen(line) - 1, j <= (strlen(line) - 1));
if (j == (strlen(line) - 1)) // reached the last character before reaching blank
return;
letters[j] = line[j];
j++;
}
letters[j] = '\0'; // where should be blank place 0
if (j + 1 == (strlen(line) - 1)) // if the next character is the last character, meaning that the character before the last one is blank
val = line[j + 1];
else // there is space in that is not one before the last character
return; // this is where read("\n") should stop, but withou entering the while loop!
printf("Word: %s\tVal: %d\n", letters, val - '0');
// empty the line holder
line[0] = '\0';
k = 0;
}
else
{
// place the ith text character into the kth line character and print them
line[k] = text[i];
printf("line[k] = %c\ttext[i] = %c\n", line[k], text[i]);
// increment k for the next turn
k++;
}
}
}
int main()
{
char *text = "ABCD 0\nEFGH 1\nIJKL 2\nMNOP 3\nQRST 4\nUVWX 5\nYZ 5\n";
read(text);
printf("---------------------------------\n");
read("\n");
return 0;
}
还有一些要点,如果程序检测到错误,则应终止而不执行其工作。这些点由return
关键字和read(char *text)
函数中的注释指示。它们只有两个,所以我也在这里描述它们:
第28行:如果程序检测到当前字符是最后一个字符,则会在此行停止扫描。由于最后一个字符应始终以空格开头,这意味着我们到达了一行的末尾而没有退出while循环(如果我们到达' '
或'\t'
就会发生)。>
第38行:如果我们成功退出了while循环,则字符j
与line
之间应为空白。这是因为找到空白后退出了while循环(这也是因为我们以line
结束了line[j] = '\0'
)。这也意味着j+1
应该是数字,这是该行中的最后一个字符。如果不是这种情况,我们到达的数字不在数字前面,因此我们退出该函数。
read(char *text)
函数。 read(char *text)
可以完美地操作和打印第一个字符串。对于第二个(仅为"\n"
),该函数不能很好地工作。我不了解的部分是尽管条件j <= strlen(line) - 1)
进入了while循环,但条件1
却以某种方式返回了text = "\n"
。您可以看到通过运行该程序,它将在第26行上打印该信息。
答案 0 :(得分:4)
解决此类问题(以及许多其他问题)的方法是打开编译器警告。
$ clang -Wall -Wextra -std=c11 -pedantic-errors k.c
k.c:24:59: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
while (line[j] != ' ' && line[j] != '\t' && j <= (strlen(line) - 1))
~ ^ ~~~~~~~~~~~~~~~~
k.c:26:67: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
printf("%d <= %ld = %d\n", j, strlen(line) - 1, j <= (strlen(line) - 1));
~ ^ ~~~~~~~~~~~~~~~~
k.c:27:23: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
if (j == (strlen(line) - 1)) // reached the last character before reaching blank
~ ^ ~~~~~~~~~~~~~~~~
k.c:35:23: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
if (j + 1 == (strlen(line) - 1)) // if the next character is the last character, meaning that t...
~~~~~ ^ ~~~~~~~~~~~~~~~~
4 warnings generated.
比较有符号和无符号确实是这里的问题。
为了执行比较,操作数被隐式转换。 j == (strlen(line)
与(size_t)j == (strlen(line)
等效,只是后者不会产生警告。