我是编程新手。目前正在学习C语言。我现在很困惑一个在跑步后出现意外结果的问题。
问题是 -
我想创建一个程序,比用户输入ABC.age = 21
时更多地输入输入并停止输入后输入并打印用户在42
之前键入的所有数字。
例如 - 输入:
42
输出:
1
2
88
42
99
我的计划 -
1
2
88
当我输入与例子中相同的值时,我得到意想不到的结果,如 -
#include <stdio.h>
int main()
{
int i = 1, j, temp;
printf("enter numbers:\n");
while (i)
{
scanf("%d", &temp);
i++;
int a[i];
a[i - 2] = temp;
if (temp == 42)
{
scanf("%d", &a[i - 1]);
for (j = 0 ; j < i - 1 ; j++)
{
if (a[j] == 42)
break;
else
printf("%d\n",a[j]);
}
}
if (temp == 42)
break;
}
return 0;
}
请帮忙。对不起我的英语不好。提前谢谢。
答案 0 :(得分:1)
您正在打印未初始化的值,因为如果i
的值变为3
且值更大,则您永远不会设置a[0]
以及a[i - 2]
之前的所有值。
因此在以下行导致Undefined Behavior
printf("%d\n", a[j]);
某些值未初始化,您仍尝试打印它们。
您应该注意到a
在每次迭代时都被重新声明,并且您没有初始化值,因为前一个a
中的值仅在上一次迭代中有效。
a
变量仅在while
循环的范围内有效,但不仅因为它未在外部声明,还因为它在超出范围时被释放。也许一个例子会让它更清晰。
假设您有以下程序
int main(void)
{
int *pointer = NULL;
if (pointer == NULL)
{
int array[5] = {1, 2, 3, 4, 5};
pointer = array;
}
/* `poitner' points to `array` but array was deallocated */
for (int i = 0 ; i < 5 ; ++i)
printf("%d\n", pointer[i]); /* This is UB */
return 0;
}
这会编译,但是你可以看到它会调用未定义的行为。
由于无法理解代码的作用,我建议如下
#include <stdio.h>
int main()
{
int i = 1;
int a[100];
printf("enter numbers:\n");
while (i++ < 100)
{
if (scanf("%d%*c", &a[i - 2]) != 1)
return -1; /* this was invalid input, it will cause UB */
if (a[i - 2] == 42)
{
if (scanf("%d%*c", &a[i - 1]) != 1)
return -1; /* this was invalid input, it will cause UB */
for (int j = 0 ; j < i - 1 ; j++)
{
if (a[j] == 42)
break;
else
printf("%d\n", a[j]);
}
}
if (a[i - 2] == 42)
break;
}
return 0;
}
这至少可以消除恶意行为并使代码更具可读性,但目前还不清楚这个程序是什么或它应该做什么。
答案 1 :(得分:0)
一般情况下,由于输入值的数量未知,您需要为新输入的值动态分配存储空间。
所以我会建立一个包含输入值的列表。另一种方法是在输入新值时对整个数组使用<h1>404 - Page not found</h1>
和malloc
。在我看来,这比建立一个列表更糟糕。
程序可以按以下方式查看
realloc
如果要输入以下值
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
struct node
{
int value;
struct node *next;
} * head = NULL;
struct node **current = &head;
int value;
int next = -1;
while ( next != 1 && scanf( "%d", &value ) == 1 )
{
if ( next == 0 || value == 42 ) ++next;
if ( next == -1 )
{
*current = malloc( sizeof( struct node ) );
( *current )->value = value;
( *current )->next = NULL;
current = &( *current )->next;
}
}
while ( head )
{
printf( "%d\n", head->value );
struct node *tmp = head;
head = head->next;
free( tmp );
}
}
然后程序输出
1 2 3 4 5 6 7 8 9 42 10
该列表在42之后既不存储42也不存储下一个值,但您可以修改程序以便存储这些值。
至于你的代码,至少这句话
1
2
3
4
5
6
7
8
9
当i等于1时,错误,导致程序的行为未定义。 我不认为我会被改变。
答案 2 :(得分:-1)
你正在做一些不必要的事情。 你必须检查一下 -
while(input_number)
{
if(input_number==42)
break;
else
printf("%d\n",input_number);
}
在我的想法中,我根据您的代码编辑了代码,以便在42
之前存储所有数字。
#include<stdio.h>
int main()
{
int i=1,j,temp;
int a[10010];
printf("enter numbers:\n");
while(i)
{
scanf("%d",&temp);
i++;
a[i-2]=temp;
if(temp==42)
{
for(j=0; j<i-2; j++)
{
if(a[j]==42)
break;
else
printf("%d\n",a[j]);
}
}
if (temp == 42)
break;
}
return 0;
}
答案 3 :(得分:-1)
我认为你的问题是试图用不同的值多次声明(和重新声明)a [i]。编译器需要在编译时知道数组的大小。因此,编译器为具有一个元素的整数数组预留内存,然后代码的动态部分尝试将其重新声明为运行时。尝试移动while循环外部并使用明确定义的最大整数值来声明它,如:
#define MAX_NUMS 1000
int a[MAX_NUMS];
上面列出了一些其他问题,但是我使用GCC 4.9编译器进行了测试,它似乎给出了预期的结果。