首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >档案编号

档案编号
EN

Stack Overflow用户
提问于 2020-03-26 22:27:09
回答 3查看 50关注 0票数 0

目前,我正试图计算一个文件中的数字。我试过这样做:

代码语言:javascript
复制
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。有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-03-27 00:42:56

下列拟议守则:

machine

  • performs

  • 实现了一个2状态,所需的functionality
  1. cleanly编译

现在,拟议的守则:

代码语言:javascript
复制
#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 );
}

针对包含以下内容的文件运行:

代码语言:javascript
复制
3 5 2 2 0 4

产出如下:

代码语言:javascript
复制
number of numbers: 6
票数 0
EN

Stack Overflow用户

发布于 2020-03-26 23:06:11

我认为,strspn(3)应该能够在这里完成大部分的腿活。下面是一个示例,说明如何计算字符串中的初始正整数数:

代码语言:javascript
复制
#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;
}

您应该能够将其与您已经开始工作的循环结合起来。

票数 0
EN

Stack Overflow用户

发布于 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,.)它将不起作用,需要进行修改/调整以适应。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60877137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档