多次运行该函数时的结果不同 - C.
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多次运行该函数时的结果不同 - C.相关的知识,希望对你有一定的参考价值。
我已经编写了一个函数,当我运行它一旦它完美运行时,但是当我用不同的输入运行它多次出错时。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20
int SumStr(char *str) {
int i = 0, j = 0, num = 0, tempnum = 0;
char temp[MAX_SIZE];
while (*(str + i) != 0) { //While not NULL - Checked
while (((*(str + i)) >= 48) && ((*(str + i)) <= 57)) { //while str[i] is [0-9]
*(temp + j) = *(str + i);
++j; ++i;
}
if (j != 0) {
tempnum = atoi(temp);
num = tempnum + num;
tempnum = 0;
j = 0;
}
++i;
}
return num;
}
void Test3(char *arr, int sum)
{
int tempSum = SumStr(arr);
if (tempSum != sum)
{
printf("Your Output is %d, Expected: %d (-3)
", tempSum, sum);
}
}
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}
该函数的目的是对字符串中的所有数字求和。
当我用这个主程序运行一次这个功能时(例如),它运行得很好;
void main() {
Test3("1$0!100", 101);
}
Output: num=101
但是当main使用不同的输入多次运行该函数时,输出完全错误。
这个主要的输出;
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
}
是;
Your Output is 6871, Expected: 15
Your Output is 6718, Expected: 1234
Your Output is 5024, Expected: 101
一个问题是,在将temp
字符传递给' '
之前,不要使用atoi
字符终止它。你可以写:
temp[j] = ' '; // or: *(temp + j) = ' ';
if (j != 0) { ...
请注意,将未使用' '
正确终止的字符序列传递给期望(已终止)字符串的函数会产生未定义的行为;这可能是你观察到的。
其次,如果输入字符串的最后一个字符是数字,则增加i
两次,从而错过输入的字符串终止字符。这再次导致未定义的行为。为了解决这个问题,你可以在增加i
之前检查你是否在字符串的末尾:
if (*(str + i) != 0) {
++i;
}
除了不终止temp[j]
之外,你还可以通过在内循环和外循环中递增str
来跳过i
中的终止字符。当你跳过终止时,它开始处理下一个字符串[或取决于你的编译器/操作系统,任何旧的垃圾]。
顺便说一下,while (isdigit(str[i]))
不仅比你的更具可读性,便携性和高效性,它还使评论变得不必要。
我想祝贺Lior Gingihashvili使用问题中显示的测试代码。也就是说,IMO是一种很好的工作方式。
此代码不会尝试修复原始代码 - 这已经由accepted answer完成。此代码显示了一种完全不同的方法来解决问题。它使用一组不同的库函数 - strcspn()
和strtol()
- 它避免了对源字符串的任何复制(因此它不会遇到null终止字符串的问题)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static
int SumStr(const char *str)
{
int sum = 0;
str += strcspn(str, "0123456789");
while (*str >= '0' && *str <= '9')
{
/*
** Since *str is a digit, the value will not be negative and
** strtol() won't fail unless the value is too big for a long.
** Since we can't include <limits.h> (or <assert.h>, or
** <errno.h>), I plan to ignore overflow.
*/
char *eon;
long val = strtol(str, &eon, 10);
sum += (int)val;
str = eon + strcspn(eon, "0123456789");
}
return sum;
}
static
void Test3(char *arr, int sum)
{
int tempSum = SumStr(arr);
const char *pass_fail = (tempSum == sum) ? "**PASS**" : "!!FAIL!!";
printf("%s Output: %5d, Expected: %5d, Data (%s)
",
pass_fail, tempSum, sum, arr);
}
int main(void)
{
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
Test3("x$.!-_+", 0);
Test3("xxx1000y2345z3456=23412!", 30213);
Test3("-0+0-0+0-", 0);
return 0;
}
运行时,代码生成:
**PASS** Output: 19, Expected: 19, Data (ax3b5mt11f)
**PASS** Output: 15, Expected: 15, Data (5$5$5)
**PASS** Output: 1234, Expected: 1234, Data (1234)
**PASS** Output: 101, Expected: 101, Data (1$0!100)
**PASS** Output: 3, Expected: 3, Data (1$1!1)
**PASS** Output: 0, Expected: 0, Data (x$.!-_+)
**PASS** Output: 30213, Expected: 30213, Data (xxx1000y2345z3456=23412!)
**PASS** Output: 0, Expected: 0, Data (-0+0-0+0-)
(是的:当我在代码中出现错误时,我确实得到了!!FAIL!!
行。)
正确运行程序:
//Explanations in the commemnts
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define MAX_SIZE 20
int SumStr(char *str) {
int i = 0, j = 0, num = 0, tempnum = 0;
char temp[MAX_SIZE];
while (*(str + i) != 0) {
//While not NULL - Checked
while ( (( *(str + i)) >= '0') && ((*(str + i)) <= '9') ) // more readable
{ //while str[i] is [0-9]
*(temp + j) = *(str + i);
++j;
++i;
}
if (j != 0) {
*(temp + j) = 0; // termination of the string needed for atoi
tempnum = atoi(temp);
num = tempnum + num;
tempnum = 0;
j = 0;
}
// new:
if (*(str + i) != 0) {
++i;
}
else break; // detection of the end of string
}
return num;
}
void Test3(const char *arr, int sum)
{
int tempSum = SumStr(arr);
if (tempSum != sum)
{
printf("Your Output is %d, Expected: %d (-3)
", tempSum, sum);
}
}
void main() {
Test3("ax3b5mt11f", 19);
Test3("5$5$5", 15);
Test3("1234", 1234);
Test3("1$0!100", 101);
Test3("1$1!1", 3);
return 0;
}
以上是关于多次运行该函数时的结果不同 - C.的主要内容,如果未能解决你的问题,请参考以下文章