C 中下溢时损坏的 fgets 输入
Broken fgets input when underflow in C
我正在尝试制作一个字符串逆向程序。我正在尝试使用 over/underflow 修复错误。我修复了第一个,所以现在我设置 MAX = 8 只是为了更容易调试。
它工作正常。但是当我的输入比MAX短时,程序就崩溃了。
因此,如您所见,字符串“QWERTY ASDFGH”被正确剪切,我有“QWERTY A”(正好是 8 个字符),然后程序将其反转,输出为“A YTREWQ”。它完全符合我的要求。
但是如果实际长度小于8,我按回车,没有任何反应。我必须按两次,输入和输出仍然损坏。
输出换行,但这不是它必须的工作方式。
这是我的源代码:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MAX 8 // not including '[=10=]' symbol
void printAsterisks(uint8_t);
void clearInputBuffer(void);
int main(void) {
char word[MAX + 1], temp;
int length, index;
printAsterisks(46);
printf("Please, type in any string. To exit give me #.\n");
printAsterisks(46);
while(1) {
index = 0;
printf("Your string : ");
fgets(word, MAX + 1, stdin);
if(word[0] == '#') {
printAsterisks(39);
printf("The program has been cancelled by User.\n");
printAsterisks(39);
break;
}
clearInputBuffer();
length = strlen(word);
for(index = 0; index < length / 2; index++) {
temp = word[index];
word[index] = word[length - index - 1];
word[length - index - 1] = temp;
}
printf("Reversed : %s\n", word);
}
return 0;
}
void printAsterisks(uint8_t count) {
for(uint8_t i = 0; i < count; i++) {
printf("*");
}
printf("\n");
}
void clearInputBuffer(void) {
static char buff;
while((buff = getchar()) != '\n' && buff != EOF);
}
正如@Some programmer dude所说,clearInputBuffer
函数无效,我稍微修改了一下。我假设你的意思是清除 word
。我还使 word
和 temp
全局化,并在解析字符串并反转它之后而不是之前调用 clearInputBuffer
。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MAX 8 // not including '[=10=]' symbol
char word[MAX + 1], temp;
void printAsterisks(uint8_t);
void clearInputBuffer(void);
int main(void) {
int length, index;
printAsterisks(46);
printf("Please, type in any string. To exit give me #.\n");
printAsterisks(46);
while(1) {
index = 0;
fgets(word, MAX + 1, stdin);
if(word[0] == '#') {
printAsterisks(39);
printf("The program has been cancelled by User.\n");
printAsterisks(39);
break;
}
length = strlen(word);
for(index = 0; index < length / 2; index++) {
temp = word[index];
word[index] = word[length - index - 1];
word[length - index - 1] = temp;
}
printf("Reversed : %s\n", word);
clearInputBuffer();
}
return 0;
}
void printAsterisks(uint8_t count) {
for(uint8_t i = 0; i < count; i++) {
printf("*");
}
printf("\n");
}
void clearInputBuffer() {
int i;
for (i = 0; word[i] != '[=10=]'; i ++) {
word[i] = '[=10=]';
}
}
问题是您试图刷新输入缓冲区。
fgets
调用读取缓冲区中的换行符,如果它适合。
当您输入少于 MAX
个字符时,fgets
调用将读取换行符,但您仍然调用 clearInputBuffer
,它将尝试读取直到 下一个换行。
您需要检查缓冲区 word
是否包含换行符,只有在没有换行符时才调用 clearInputBuffer
。
您可以使用 strcspn
函数来检查换行符,并使用其返回的位置来设置空终止符以从缓冲区中“删除”换行符:
// strcspn will return the beginning index of the sub-string you search for
// Or the index of the null-terminator if the sub-string wasn't found
size_t newline_pos = strcspn(word, "\n");
if (word[newline_pos] == '\n')
{
// There's a newline in the input, remove it
word[newline_pos] = '[=10=]';
}
else
{
// There's no newline, skip the remainder of the line
clearInputBuffer();
}
我正在尝试制作一个字符串逆向程序。我正在尝试使用 over/underflow 修复错误。我修复了第一个,所以现在我设置 MAX = 8 只是为了更容易调试。 它工作正常。但是当我的输入比MAX短时,程序就崩溃了。
因此,如您所见,字符串“QWERTY ASDFGH”被正确剪切,我有“QWERTY A”(正好是 8 个字符),然后程序将其反转,输出为“A YTREWQ”。它完全符合我的要求。
但是如果实际长度小于8,我按回车,没有任何反应。我必须按两次,输入和输出仍然损坏。 输出换行,但这不是它必须的工作方式。
这是我的源代码:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MAX 8 // not including '[=10=]' symbol
void printAsterisks(uint8_t);
void clearInputBuffer(void);
int main(void) {
char word[MAX + 1], temp;
int length, index;
printAsterisks(46);
printf("Please, type in any string. To exit give me #.\n");
printAsterisks(46);
while(1) {
index = 0;
printf("Your string : ");
fgets(word, MAX + 1, stdin);
if(word[0] == '#') {
printAsterisks(39);
printf("The program has been cancelled by User.\n");
printAsterisks(39);
break;
}
clearInputBuffer();
length = strlen(word);
for(index = 0; index < length / 2; index++) {
temp = word[index];
word[index] = word[length - index - 1];
word[length - index - 1] = temp;
}
printf("Reversed : %s\n", word);
}
return 0;
}
void printAsterisks(uint8_t count) {
for(uint8_t i = 0; i < count; i++) {
printf("*");
}
printf("\n");
}
void clearInputBuffer(void) {
static char buff;
while((buff = getchar()) != '\n' && buff != EOF);
}
正如@Some programmer dude所说,clearInputBuffer
函数无效,我稍微修改了一下。我假设你的意思是清除 word
。我还使 word
和 temp
全局化,并在解析字符串并反转它之后而不是之前调用 clearInputBuffer
。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define MAX 8 // not including '[=10=]' symbol
char word[MAX + 1], temp;
void printAsterisks(uint8_t);
void clearInputBuffer(void);
int main(void) {
int length, index;
printAsterisks(46);
printf("Please, type in any string. To exit give me #.\n");
printAsterisks(46);
while(1) {
index = 0;
fgets(word, MAX + 1, stdin);
if(word[0] == '#') {
printAsterisks(39);
printf("The program has been cancelled by User.\n");
printAsterisks(39);
break;
}
length = strlen(word);
for(index = 0; index < length / 2; index++) {
temp = word[index];
word[index] = word[length - index - 1];
word[length - index - 1] = temp;
}
printf("Reversed : %s\n", word);
clearInputBuffer();
}
return 0;
}
void printAsterisks(uint8_t count) {
for(uint8_t i = 0; i < count; i++) {
printf("*");
}
printf("\n");
}
void clearInputBuffer() {
int i;
for (i = 0; word[i] != '[=10=]'; i ++) {
word[i] = '[=10=]';
}
}
问题是您试图刷新输入缓冲区。
fgets
调用读取缓冲区中的换行符,如果它适合。
当您输入少于 MAX
个字符时,fgets
调用将读取换行符,但您仍然调用 clearInputBuffer
,它将尝试读取直到 下一个换行。
您需要检查缓冲区 word
是否包含换行符,只有在没有换行符时才调用 clearInputBuffer
。
您可以使用 strcspn
函数来检查换行符,并使用其返回的位置来设置空终止符以从缓冲区中“删除”换行符:
// strcspn will return the beginning index of the sub-string you search for
// Or the index of the null-terminator if the sub-string wasn't found
size_t newline_pos = strcspn(word, "\n");
if (word[newline_pos] == '\n')
{
// There's a newline in the input, remove it
word[newline_pos] = '[=10=]';
}
else
{
// There's no newline, skip the remainder of the line
clearInputBuffer();
}