目前,我正试图计算一个文件中的数字。我试过这样做:
while(fgets(fileContents, sizeof(fileContents)-1, fp))
{
if(fileContents[sizeof(fileContents)] == '\n')
fileContents[sizeof(fileContents)] = '\0';
if(fileContents[sizeof(fileContents)] == 32 )
counter++;
//parse numbers
tokenPtr = strtok(fileContents," ");
counter++;
}我有这样一串数字:3 5 2 2 0 4.所以我不知道可能有多少个数字,所以我试着计算它们之间的空格,这就是为什么你看到ASCII值#32。有什么想法吗?
发布于 2020-03-27 00:42:56
下列拟议守则:
machine
。
现在,拟议的守则:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main( void )
{
int count = 0;
enum state { NOT_IN_NUMBER, IN_NUMBER };
enum state currentState = NOT_IN_NUMBER;
FILE *fp = fopen( "myInputFile.txt", "r" );
if( !fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
int ch;
while( (ch = fgetc(fp)) != EOF )
{
//printf( "%d\n", ch ); //debugging
if( isdigit( ch ) )
{
if( currentState == NOT_IN_NUMBER )
{
count++;
currentState = IN_NUMBER;
}
}
else
{
currentState = NOT_IN_NUMBER;
}
}
fclose( fp );
printf( "number of numbers: %d\n", count );
}针对包含以下内容的文件运行:
3 5 2 2 0 4产出如下:
number of numbers: 6发布于 2020-03-26 23:06:11
我认为,strspn(3)应该能够在这里完成大部分的腿活。下面是一个示例,说明如何计算字符串中的初始正整数数:
#include <string.h>
int n_nums(const char *str)
{
int n = 0;
do {
/* Skip over any whitespace */
str += strspn(str, " \t\r\n");
if (!strspn(str, "0123456789"))
/* Not a number, we're done */
break;
/* Skip over the number. */
str += strspn(str, "0123456789");
/* Iff the next char is NUL or whitespace, we just
* skipped over a valid number. */
switch (*str) {
case '\0':
case ' ':
case '\t':
case '\r':
case '\n':
n++;
}
} while (*str);
return n;
}您应该能够将其与您已经开始工作的循环结合起来。
发布于 2020-03-27 01:34:12
我会:
( a)获取文件的大小和内存,映射文件(例如使用mmap()),这样它就像一个大数组的uint8_t。或者,您可以以任何其他方式将文件加载到内存中。
( b)对于uint8_t数组中的每个字节;XOR为0x30。这使得数字字符成为0x00到0x09范围内的值,其他的都是更大的值。
c)对于uint8_t数组中的每个字节;如果大于0x09,则将其设置为0x00,如果没有将其设置为0x01。
( d)对于uint8_t数组中的每个字节;使用下一个字节对其进行异或。在此之后,0x01表示数字字符序列的开始或结尾。
( e)对于uint8_t数组中的每个字节,将其值添加到计数器中。这给出了开始或结束(一个或多个)数字数字序列的次数。通过将这个计数除以2(因为你只想要“开始”而不是“开始和结束”),你就可以得到你想要的答案。
请注意,所有这些步骤(除了第一个步骤)都可以用一个循环来完成;对于您或编译器来说,使用SIMD进行优化都很简单(因此,像XOR这样的单个操作可以并行地处理多个字节--例如,AVX-512可以同时处理多达64个字节)。因此,它期望性能主要由数据获取(如果存在“操作系统的文件系统缓存缺失”,则为磁盘IO,CPU缓存丢失,等等)。
此外,这只适用于简单整数(例如,字符串"$123,456,789.01“将被计算为4个数字,而不是一个数字);它不会检测/不会受到任何溢出的影响(例如,字符串"9999999999999999999999999999999999999999999999999999999999999999999999999999999999999”不会造成问题,而是将被视为有效数字)。
最后,这都假设字符编码是ASCII或UTF-8。任何其他字符编码(EBCDIC,UTF-16,.)它将不起作用,需要进行修改/调整以适应。
https://stackoverflow.com/questions/60877137
复制相似问题