C 尽可能高效地进行字符串检查和表分配
我想知道是否有人可以帮我尝试一个赋值,并对这种类型的字符串进行轻微检查:C 尽可能高效地进行字符串检查和表分配,c,string,C,String,我想知道是否有人可以帮我尝试一个赋值,并对这种类型的字符串进行轻微检查: A=[a1,a2,a3,a4]/[b1,b2,b3,b4] 其中,ai,bi是可以精确到0.000的浮点数,例如: A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541] 之后,我打算使用两个浮点数组,一个用于存储ai,另一个用于bi。诸如此类: float array_a[4] , array_b[4]; array_a[0] = a1; array_a[1
A=[a1,a2,a3,a4]/[b1,b2,b3,b4]
其中,ai,bi是可以精确到0.000的浮点数,例如:
A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541]
之后,我打算使用两个浮点数组,一个用于存储ai,另一个用于bi。诸如此类:
float array_a[4] , array_b[4];
array_a[0] = a1;
array_a[1] = a2;
array_a[2] = a3;
array_a[3] = a4;
array_b[0] = b1;
array_b[1] = b2;
array_b[2] = b3;
array_b[3] = b4;
我知道如何使用strcmp和atof等函数来实现,但它们会占用PIC一半以上的内存。我在找效率更高的东西
我现在所拥有的:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
float array_a[4] , array_b[4];
char txt[55] = "A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541]";
char *ptChar,str1[4]="";
int i;
strcpy(str1, "A=[");
if(strncmp(txt,str1,3) == 0)
{
ptChar = txt+3;
for (i = 0 ; i < 4 ; i++)
{
array_a[i] = atof(ptChar);
ptChar += 5;
if (* ptChar == ',' || * ptChar == ' ')
ptChar++;
}
strcpy(str1, "]/[");
if(strncmp(ptChar,str1,3) == 0)
{
ptChar += 3;
for (i = 0 ; i < 4 ; i++)
{
array_b[i] = atof(ptChar);
ptChar += 5;
if (* ptChar == ',' || * ptChar == ' ')
ptChar++;
}
}
}
return 0;
}
#包括
#包括
#包括
int main()
{
浮点数组_a[4],数组_b[4];
char txt[55]=“A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541]”;
char*ptChar,str1[4]=“”;
int i;
strcpy(str1,“A=[”);
如果(strncmp(txt,str1,3)==0)
{
ptChar=txt+3;
对于(i=0;i<4;i++)
{
数组_a[i]=atof(ptChar);
ptChar+=5;
如果(*ptChar==”,“| |*ptChar==”)
ptChar++;
}
strcpy(str1,“]/[”);
if(strncmp(ptChar,str1,3)==0)
{
ptChar+=3;
对于(i=0;i<4;i++)
{
数组_b[i]=atof(ptChar);
ptChar+=5;
如果(*ptChar==”,“| |*ptChar==”)
ptChar++;
}
}
}
返回0;
}
这不起作用,除了它不是有效的,如果A的字符数不同,也就是说,如果新的A是:A=[0.5,-0.215,5.504,7.552]/[-0.01,0.554,0.584,0.541]
它将不再有效,而且它也不考虑可能的减号,因此也不起作用
非常感谢您的帮助。如果您知道您的输入行为良好,您可以使用
*scanf
函数系列,如下所示:
if ( sscanf( txt, "A=[%f,%f,%f,%f]/[%f,%f,%f,%f]",
&array_a[0], &array_a[1], &array_a[2], &array_a[3],
&array_b[0], &array_b[1], &array_b[2], &array_b[3] ) != 8 )
{
// handle bad input
}
else
{
// process normally
}
编辑
作为对注释的响应,这里有一个方法,它根本不使用任何库函数进行解析,并且可以处理不同数量的值:
#include <stdio.h>
/**
* Convert the floating point values in `str`, assign the first
* set to the array a and the second set to the array b. Return
* the number of elements for each. This routine performs NO
* error checking - it is assumed the target arrays are large
* enough to handle the number of elements in the string. It
* also assumes in the input is well-behaved structurally and
* that the format is *at least* "[f,f,f...]/[f,f,f...]". It
* ignores the leading "A=" - if that matters you will need to
* tweak this. However, it should be relatively straightforward
* to figure that out from what I've done so far.
*/
void parse( const char *str, double *a, size_t *asize, double *b, size_t *bsize )
{
/**
* Instead of a bunch of special case logic in the switch statement
* below, we'll use a temporary variable to point to whichever
* target array we're writing to. Until we see the '/' character,
* we're writing to array a - after we see it, we write to array b.
* Same principle with tsize.
*/
double *t = a;
size_t *tsize = asize;
/**
* We convert the floating point value one character at time,
* and the following variables keep track of the conversion
* state. tmp is the working value. If we see a leading '-'
* then we set sign to -1. If we see the '.' we set dot to 1.
* After we see the dot, we multiply each new digit by mag and
* add the result to tmp, then divide mag by 10.
*/
double tmp = 0;
int sign = 1;
int dot = 0;
double mag = 0.1;
/**
* Loop until we see the string terminator.
*/
while ( *str )
{
switch ( *str )
{
/**
* Ignore all whitespace.
*/
case ' ':
case '\n':
case '\t':
break;
/**
* Start writing to target array b
*/
case '/':
t = b;
tsize = bsize;
break;
/**
* Negate the value.
*/
case '-':
sign = -1;
break;
/**
* Saw the decimal point.
*/
case '.':
dot = 1;
break;
/**
* Comma or close bracket marks the end of a floating
* point value, assign the result to the current target
* array and reset our state variables.
*/
case ',':
case ']':
t[(*tsize)++] = tmp * sign;
tmp = 0;
sign = 1;
dot = 0;
mag = 0.1;
break;
/**
* Convert the next digit. If we haven't seen the dot yet,
* multiply tmp by 10 and add the new digit. If we have seen
* the dot, multiply the next digit by mag and then divide
* mag by 10 and add the result to tmp. Since 0.1, 0.01, etc.
* don't have exact binary floating point representations this
* does introduce some error, but if you only need to be
* accurate to three decimal places it doesn't matter that much.
*/
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if ( !dot )
{
tmp *= 10;
tmp += *str - '0';
}
else
{
tmp += (*str - '0') * mag;
mag /= 10.0;
}
break;
default:
break;
}
str++;
}
}
int main( int argc, char **argv )
{
if ( argc < 2 )
{
fprintf( stderr, "USAGE: %s input_string\n", argv[0] );
return -1;
}
double a[10], b[10];
size_t asize, bsize;
/**
* Convert the command line input.
*/
parse( argv[1], a, &asize, b, &bsize );
for ( size_t i = 0; i < asize; i++ )
printf( "a[%zu] = %7.3lf\n", i, a[i] );
for ( size_t i = 0; i < bsize; i++ )
printf( "b[%zu] = %7.3lf\n", i, b[i] );
return 0;
}
同样,此例程不执行、零、零、nada错误检查或验证,它基本上忽略了前面的
“A=”
,因此如果这很重要,您需要对其进行调整。但是,基本结构应该清晰,添加逻辑应该相对简单。检查这是否有帮助,它调用并推进ptr
填充数组,同时有文本要扫描,,“
和]”是分隔符,我还使用2D数组来简化代码。始终避免使用幻数,它们容易出错:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
// Do not hardcode 55
char txt[] = "A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541]";
char *ptr = txt;
enum {rows = 2, cols = 4};
float array[rows][cols];
int row = 0, col = 0;
while (*ptr)
{
// Check for out of bound access
if ((row == rows) || (col == cols))
{
fprintf(stderr, "Can not write at this location\n");
exit(EXIT_FAILURE);
}
float num = strtof(ptr, &ptr);
if ((*ptr == ',') || (*ptr == ']'))
{
array[row][col++] = num;
if (*ptr == ']')
{
row++;
col = 0;
}
}
ptr++;
}
for (row = 0; row < rows; row++)
{
for (col = 0; col < cols; col++)
{
printf("%f\n", array[row][col]);
}
}
return 0;
}
#包括
#包括
内部主(空)
{
//不要硬编码55
字符txt[]=“A=[0.500,-0.215,5.504,7.552]/[-0.001,0.554,0.584,0.541]”;
char*ptr=txt;
枚举{rows=2,cols=4};
浮点数组[行][cols];
int行=0,列=0;
while(*ptr)
{
//检查越界访问
如果((行==行)| |(列==列))
{
fprintf(stderr,“无法在此位置写入\n”);
退出(退出失败);
}
float num=strtof(ptr和ptr);
如果((*ptr==',')| |(*ptr==']'))
{
数组[行][col++]=num;
如果(*ptr==']')
{
行++;
col=0;
}
}
ptr++;
}
对于(行=0;行<行;行++)
{
for(col=0;col
当您转换为浮点时,可以使用strof()函数(而不是atof),该函数的优点是它会告诉您字符串中出现的第一个非浮点数字的结尾,该数字可用于转换循环中字符串的下一个浮点
而不是这个,
for (i = 0 ; i < 4 ; i++)
{
array_a[i] = atof(ptChar);
ptChar += 5;
if (* ptChar == ',' || * ptChar == ' ')
ptChar++;
}
同样,对数组_b使用的for循环进行相同的更改。
编辑:如果数字浮动在字符串中是可变的(不总是4个),循环终止条件将被更新。而且我也不会总是从每个组件中获得4个术语。。。也许我在之前的信息中没有说清楚。。。例如,A也可以是:A=[a1,a2,a3]/[b1,b2]
。我提出的另一个案例可能是最大的。@AlejandroFernándezSuárez:啊。那就不行了。我有一个不同的解决方案,它不依赖于任何库函数,但我需要时间来解决它。@AlejandroFernándezSuárez:请参阅我的编辑。非常感谢您的帮助非常感谢您的帮助:谢谢您的帮助D
for (i = 0 ; i < 4 ; i++)
{
array_a[i] = atof(ptChar);
ptChar += 5;
if (* ptChar == ',' || * ptChar == ' ')
ptChar++;
}
for( i = 0 ; *ptChar && *ptChar != ']' ; i++ )
{
array_a[i] = strtof(ptChar, &ptChar); // Using strtof instead of atof
if (* ptChar == ',' || * ptChar == ' ')
ptChar++;
}