我一直试图弄清楚这一点,并且没有在网上找到任何有关此行为的信息。我认为它是C语言特有的东西,所以我把它放在这里试图了解它是什么。当以下函数将其名称更改为main并编译并自行运行时,它正是我正在寻找的内容:
void print_to_screen(void) {
system("clear");
char *usor;
usor = malloc(9 * sizeof(char));
if(sizeof(getenv("USER")) > 8)
return;
usor = getenv("USER");
FILE *inFile;
char buf[BUFSIZ];
char fileIn[30];
sprintf(fileIn, "/home/%s/output3", usor);
if((inFile = fopen(fileIn, "r")) == NULL) {
perror(fileIn);
return;
}
int lines = 0;
int count = 0;
int i = 0;
while(fgets(buf, BUFSIZ, inFile) != NULL)
lines++;
if(lines == 0) {
printf("Sortact empty. Press enter.");
getchar();
return;
}
rewind(inFile);
for(i = 0; i <= PAGE; i++) {
if(count == 0) {
printf("%d accounts worked\n", lines);
//sleep(2);
printf(" %-8s %-8s %8s %8s %8s %8s\n", "begin", "end", "msg #", "activity", "response", "next_act");
//sleep(2);
}
if(lines == count) {
printf("End of output. Press enter.");
fclose(inFile);
getchar();
return;
}
fgets(buf, BUFSIZ, inFile);
count++;
printf("%3d %s", count, buf);
}
while(fgets(buf, BUFSIZ, inFile) != NULL) {
printf("q) to quit, Enter) for line-by-line feed, 'b') backup, *) next page\n");
char c = getchar();
if(c == 'b') {
if(count == PAGE)
continue;
system("clear");
count -= 2;
rewind(inFile);
for(i = count; i > 0; i--) {
fgets(buf, BUFSIZ, inFile);
printf("%3d %s", count, buf);
}
continue;
}
else if(c == '\n') {
if(lines == count) {
printf("End of output. Press enter.");
fclose(inFile);
getchar();
return;
}
system("clear");
count++;
rewind(inFile);
i = count;
count = 0;
for(; i > 0; i--) {
fgets(buf, BUFSIZ, inFile);
count++;
printf("%3d %s", count, buf);
}
continue;
}
else if(c == 'q') {
return;
}
else {
if(lines == count) {
printf("End of output. Press enter.");
fclose(inFile);
getchar();
return;
}
system("clear");
for(i = 0; i <= PAGE; i++) {
if(lines == count) {
printf("End of output. Press enter.");
fclose(inFile);
getchar();
return;
}
fgets(buf,BUFSIZ, inFile);
count++;
printf("%3d %s", count, buf);
}
continue;
}
}
fclose(inFile);
}
但是,当我作为一个单独的函数从以下switch语句运行时,它会切断前两行输出(工作帐户和标题行):
while(c == 0) {
printf("1) print to the screen, most recent first\n");
printf("2) print to the screen, least recent first\n");
printf("3) print to paper\n");
printf("4) cancel\n");
c = getchar();
switch(c) {
case '1' :
sprintf(sort_c, "sort -r -k1.1,1.2 -k1.4,1.5 -k1.7,1.8 /home/%s/output2 > /home/%s/output3", usor, usor);
free(usor);
system(sort_c);
print_to_screen();
return 0;
case '2' :
sprintf(sort_c, "sort -k1.1,1.2 -k1.4,1.5 -k1.7,1.8 /home/%s/output2 > /home/%s/output3", usor, usor);
free(usor);
system(sort_c);
print_to_screen();
return 0;
case '3' :
sprintf(sort_c, "sort -k1.1,1.2 -k1.4,1.5 -k1.7,1.8 /home/%s/output2 > /home/%s/output3", usor, usor);
system(sort_c);
sprintf(print_c, "qprt -Plp3 /home/%s/output3", usor);
system(print_c);
free(usor);
return 0;
case '4' :
free(usor);
return 0;
default :
c = 0;
system("clear");
break;
}
}
我尝试删除循环以及大约十亿个其他内容,但没有任何帮助这种行为。前两行最初是在他们现在所处的循环之前。那些注释掉的sleep()语句告诉我这些行都被打印 - 一个然后另一个 - 然后它们被清除了。如果有人能帮我理解发生的事情,我将不胜感激。
由于
(哦,这是一个更大的程序的一部分,“usor”变量将被检查。我知道如果我不添加这个哈哈,我可能会陷入地狱。)
预期的输出是:
46个帐户有效 开始结束消息#活动响应next_act 1 12:44:29 13:04:19 0012497389 CR CS 2 08:40:28 08:54:40 0012498082 ZZ ZZ ZZ 3 08:40:06 08:40:22 0012500689 ZZ ZZ ZZ 4 08:39:47 08:39:59 0011906009 ZZ ZZ ZZ 5 08:39:31 08:39:43 0012199860 ZZ ZZ ZZ 6 08:39:04 08:39:27 0012499803 ZZ ZZ ZZ 7 08:37:58 08:38:50 0012514625 ZZ ZZ ZZ 8 08:37:18 08:37:55 0012224477 ZZ ZZ ZZ 9 08:37:03 08:37:15 0012169778 ZZ ZZ ZZ 10 08:36:20 08:36:59 0012499231 ZZ ZZ ZZ 11 08:36:06 08:36:17 0012501138 ZZ ZZ ZZ 12 08:34:58 08:36:00 0012206191 ZZ ZZ ZZ 13 08:34:20 08:34:51 0012349829 ZZ ZZ ZZ 14 08:31:59 08:34:11 0012348605 ZZ ZZ ZZ 15 08:31:22 08:31:54 0012431227 ZZ ZZ ZZ 16 08:30:12 08:31:04 0012425863 ZZ ZZ ZZ 17 08:29:13 08:30:02 0012420569 CR DS 18 08:07:07 08:29:07 0012414680 ZZ ZZ ZZ 19 08:06:42 08:07:01 0012414680 CR DS 20 08:06:28 08:06:37 0012185000 ZZ ZZ ZZ 21 08:05:26 08:05:49 0012206880 ZZ ZZ ZZ 22 08:04:23 08:05:22 0011775414 ZZ ZZ ZZ q)来 退出,输入)用于逐行馈送,'b')备份,*)下一页
当它作为自己的程序运行时,我得到的是什么。这就是我没有它的原因:
12:44:29 13:04:19 0012497389 CR CS 2 08:40:28 08:54:40 0012498082 ZZ ZZ ZZ 3 08:40:06 08:40:22 0012500689 ZZ ZZ ZZ 4 08:39:47 08:39:59 0011906009 ZZ ZZ ZZ 5 08:39:31 08:39:43 0012199860 ZZ ZZ ZZ 6 08:39:04 08:39:27 0012499803 ZZ ZZ ZZ 7 08:37:58 08:38:50 0012514625 ZZ ZZ ZZ 8 08:37:18 08:37:55 0012224477 ZZ ZZ ZZ 9 08:37:03 08:37:15 0012169778 ZZ ZZ ZZ 10 08:36:20 08:36:59 0012499231 ZZ ZZ ZZ 11 08:36:06 08:36:17 0012501138 ZZ ZZ ZZ 12 08:34:58 08:36:00 0012206191 ZZ ZZ ZZ 13 08:34:20 08:34:51 0012349829 ZZ ZZ ZZ 14 08:31:59 08:34:11 0012348605 ZZ ZZ ZZ 15 08:31:22 08:31:54 0012431227 ZZ ZZ ZZ 16 08:30:12 08:31:04 0012425863 ZZ ZZ ZZ 17 08:29:13 08:30:02 0012420569 CR DS 18 08:07:07 08:29:07 0012414680 ZZ ZZ ZZ 19 08:06:42 08:07:01 0012414680 CR DS 20 08:06:28 08:06:37 0012185000 ZZ ZZ ZZ 21 08:05:26 08:05:49 0012206880 ZZ ZZ ZZ 22 08:04:23 08:05:22 0011775414 ZZ ZZ ZZ q)来 退出,输入)用于逐行馈送,'b')备份,*)下一页
是的,我已经通过gdb运行了很多次,并没有告诉我屏幕是如何清除的。
答案 0 :(得分:3)
我自己尝试编译代码。当您输入1或2作为主程序的输入时,c = getchar();
(主,第6行)仅消耗第一个字符,留下&#39; \ n&#39;在stdin中,第54行的print_to_screen
中的getchar会立即使用它。这会导致system("clear")
被调用(print_to_screen,第74行),清除标题行,再次打印{{1}行。没有标题,这看起来好像标题消失了。如果运行output3
作为主函数,则不会发生这种情况,因为运行时stdin中没有额外的输入。
您可以进行最简单的修改,即在print_to_screen
(主要,第6行)之后添加getchar();
,以删除额外的&#39; \ n&#39;来自stdin。但最好使用c = getchar();
代替fgets
,以便一次读取整行。
通常建议使用getchar
代替snprintf
(以避免缓冲区溢出),sprintf
而不是calloc
(以避免整数溢出),以及始终检查分配的返回值和malloc
。由于潜在的命令注入,用户提供的输入的fgets
调用当然非常敏感(虽然我知道你说输入是安全的)。有关详细信息,请参阅sprintf(3)和malloc(3)中的CAVEATS。