任务是:用户键入char
数组,并且当最后两个值与第一个和第二个插入值匹配时,程序停止,然后仅打印插入的int
值。
例如,我键入:1,2,f,5,2,g,s,d,c,3,1,2
并得到1,2,5,3
这是我现在所拥有的
int main()
{
setlocale(LC_ALL, "RUS");
char* A;
int i = 2, N;
//making an array
A = (char*)malloc(2 * sizeof(char));
printf("Enter an array \n");
//entering the first value
scanf_s("%c", &A[0]);
//second value
scanf_s("%c", &A[1]);
//next values
while (!(A[i - 1] == A[0] && A[i] == A[1]))
{
i++;
A = (char*)realloc(A, (i + 1)*sizeof(char));
scanf_s("%c", &A[i]);
}
system("pause");
return 0;
}
因此,现在仅当第一个值匹配并且什么也不显示时,它才会停止。我真的很困惑
最佳答案
您可以避免完全动态分配,而只需关注任务的逻辑即可。虽然可以使用scanf
来读取字符输入,但是最好使用面向字符的输入功能(例如getchar
)来提供服务。
也就是说,您似乎想从stdin
读取字符,仅在数组中存储唯一数字,然后,如果用户输入的数字与数组中存储的前两个元素匹配,则打印存储在数组中的值并退出。 (如果我有任何错,请在评论中让我知道)
首先,根据分隔字符的值,使用scanf
读取字符可能有点挑剔。但是,由于您只关心存储数字,这使事情变得容易一些。
为避免使用malloc
,只需设置一些合理的限制来调整数组大小并对照您的存储元素进行检查。您只需要一个简单的#define
。例如:
#define MAXE 128
将定义一个常量
MAXE
(用于最大元素),以便在填充数组时进行测试。只需对添加到数组中的元素进行计数即可,如果达到极限,请退出。您希望继续读取字符,直到满足以下两个条件之一:(1)您已向阵列添加了128个值,而没有退出条件被触发,或者(2)输入的最后两个字符与
a[0]
和< cc>。要设置阅读内容,您可以执行以下操作: while (n < MAXE && scanf ("%c", &c) == 1) { ...
注意:使用
a[1]
可以避免不可移植的getchar()
函数问题,以及_s
函数系列的其他陷阱。使用scanf
而不是将getchar()
声明为c
类型,将char
声明为c
类型,然后将您的分配更改为int
的更改很小,如下所示: while (n < MAXE && (c = getchar()) != EOF) {
读取一个字符(无论如何)后,您要测试它是否是一个数字,如果不是,则不存储它,并且它不能成为退出条件的一部分。因此,如果不是数字,则只需获取下一个字符:
if (c < '0' || '9' < c)
continue;
(注意:
c
提供了可以代替手动检查使用的ctype.h
功能)无论您要存储前两位数字,还是要存储前两位数字,都要存储输入的任何新数字(尚未存储),因此需要对照先前存储的所有数字测试当前数字以确保它是唯一数字。尽管可以用几种方法对逻辑进行编码,但在这种情况下,测试循环必须先测试所有存储的值,然后再决定存储当前数字。在这种情况下,以及需要在嵌套循环中中断控制的情况下,
isdigit()
语句是您最好的朋友。在这里,如果数字是重复的,则goto
会直接跳过分配的goto
标签: if (n > 1)
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c;
dupe:;
难题的最后一部分是退出条件。这有点棘手(但很容易解决),因为您知道您将不会在数组中存储前一个(对于Leffler,倒数第二个)值进行测试(该值对数组而言是唯一的)。技巧只是保存上次迭代中的字符以进行测试。 (也许在名为
dupes
的变量中)。现在,您可以编写退出子句了: if (n > 2 && a[0] == last && a[1] == c)
break;
放在一起,您可以执行以下操作:
#include <stdio.h>
#define MAXE 128
int main (void) {
char a[MAXE] = "", c, last = 'a';
int i, n = 0;
printf ("Enter an array\n");
while (n < MAXE && scanf ("%c", &c) == 1) {
if (c < '0' || '9' < c)
continue;
if (n > 1)
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c;
dupe:;
if (n > 2 && a[0] == last && a[1] == c)
break;
last = c;
}
if (n < 3) {
fprintf (stderr, "error: minimum of 3 values required.\n");
return 1;
}
if (n == MAXE) {
fprintf (stderr, "warning: limit of values reached.\n");
return 1;
}
printf ("Values in array: ");
for (i = 0; i < n; i++)
putchar (a[i]);
putchar ('\n');
return 0;
}
如何处理打印和错误情况取决于您。上面包含的内容只是关于如何覆盖基础的一种想法。
注意:gcc没有实现可选的
last
功能,因此您可以根据需要将其更改回_s
。使用/输出示例
$ ./bin/exitonmatch
Enter an array
1
2
f
5
2
g
s
d
c
3
1
2
Values in array: 1253
仔细看一下,如果您有任何问题,请告诉我。
接受任何字符作为终止符/仅存储唯一数字
如果您所解释的逻辑是跟踪前两个字符,而不管它们是否是数字,并允许任何字符充当前两个输入序列的终止检查,则最简单的处理方法是简单地存储前两个字符在一个单独的数组中输入两个字符(或两个变量),并对照它们检查输入的每个字符序列。
添加此类型检查只需要对原始条件稍作重新安排,以允许对输入的任何字符进行几项检查,然后才考虑仅将数字存储在数组中。
注意:添加了
scanf_s
(字符数)变量以跟踪输入的字符数,并添加了cc
数组以容纳输入的前两个字符。例如:
char a[MAXE] = "", first[TSTA] = "", last = 'a';
int c, cc = 0, i, n = 0;
printf ("Enter an array\n");
while (n < MAXE && (c = getchar()) != EOF) {
if (c < ' ') continue; /* skip non-print chars */
if (cc < 2) /* fill first[0] & [1] */
first[cc] = c; /* check term condition */
if (++cc > 2 && first[0] == last && first[1] == c)
break;
last = c; /* set last */
if (c < '0' || '9' < c) /* store only numbers */
continue;
if (n > 1) /* skip duplicates */
for (i = 0; i < n; i++)
if (c == a[i])
goto dupe;
a[n++] = c; /* digit and not a dupe - store it */
dupe:;
}
注意:上面使用了
first
,但是如果您愿意,可以用第一个示例中的getchar
代替。使用/输出示例
在这里,前两个字符是
scanf
和a
,尽管不是数字,它们仍作为终止序列。$ ./bin/exitonmatchgc
Enter an array
a
b
c
4
5
g
h
4
9
3
b
a
b
Values in array: 4593
关于c - 具有停止条件的阵列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37533102/