【问题标题】:How to locate and convert to integers an array of string in C?如何在C中定位字符串数组并将其转换为整数?
【发布时间】:2021-10-21 23:48:08
【问题描述】:

我有一个要解决的问题。我有一个字符串和整数数组,我只想将整数(163)转换为 C 中的实际整数。

我已设法找到我想要的数字 (163) 数组位置,但我不确定如何将它们转换为数字。我曾尝试使用 strtol、atoi 和 strtoumax,但没有成功。 我在下面添加了我的代码。

char busy[30] = {"this is; it was; 163; 234;;"};

int tag = 0;
int location = 0;
for (int i = sizeof(busy); i > 0; i--)  {
   printf("%c\n", busy[i]); 
   if (busy[i] == ';')  {
        tag = tag+1;
        printf("tag is %i \n", tag);    
   }
   if (tag == 4) {
       printf("for loop is %i\n", i);
       location = i;
       break;
   }
}
location = location+1;
int loca_saved = 0;
int loca_finish = 0;
int tag1 = 0;
while (busy[location] != ';') {
    if (busy[location] == ' ' && busy[location - 1] == ';')  {
    //printf("not printing whitespace between semicolon and characters\n");
    location++;
    }
    else    { 
        if (tag1 == 0)    {
            tag1 = tag1+1;
            loca_saved = location; //this is to tell me the array location for the first char      
        }
        if (busy[location + 1] == ';')  {
            loca_finish = location; //this is to tell me the array location for the last char
        }
    
    putchar(busy[location]); //this is to print my desired characters(163)
    location++;
    }

}

【问题讨论】:

  • “我尝试使用...”。不幸的是,您没有向我们展示您是如何尝试的,或者您的尝试以何种方式失败。您的代码不包含任何转换您的数字的尝试。

标签: arrays c string sorting integer


【解决方案1】:

这完全取决于您要解析的确切语法。请注意,例如,负整数以- 字符开头,并且必须有一个最大整数值。由于您的工作非常“低级”,您可能希望在读取字符串时执行转换为整数,例如:

#include <ctype.h>
#include <stdio.h>

int main(void)
{
    char busy[30] = {"this is; it was; 163; 234;;"};

    for (char *p = busy; *p; ++p) // Loop over the string
        if (isdigit(*p)) // Found first digit of an unsigned integer
        {
            unsigned n = (unsigned) (*p - '0'); // Store the value of the first digit in 'n'

            // While reading the number, shift the digits to the appropriate positions
            while (isdigit(*++p))
                n = n * 10U + (unsigned) (*p - '0');

            printf("%u\n", n); // We have finished parsing the integer, print it
        }
}

使用atoi 也可以,但它需要对每个整数进行两次传递:一次在atoi 本身中,另一次在您正在解析的字符串中移动。

strtol 函数允许您将指针传递给您的指针,该指针设置在读取整数之后 的一个位置,从而避免了该问题。您可以使用它来推进指针。在此代码示例中,指针要么手动推进,要么通过strtol

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char busy[30] = {"this is; it was; 163; 234;;"};

    for (char *p = busy; *p; )
        if (isdigit(*p))
            printf("%ld\n", strtol(p, &p, 10));
        else
            ++p;
}

另一种选择,不使用isdigit

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char busy[30] = {"this is; it was; 163; 234;;"};

    for (char *p = busy; *p; )
    {
        char *end;
        long n = strtol(p, &end, 10);
        if (p != end) // Pointer was advanced, so an integer was read
        {
            printf("%ld\n", n);
            p = end;
        }
        else // Pointer was not advanced, do so manually
            ++p;
    }
}

【讨论】:

  • 嗨云,在你的第一个代码中,你有 %u?我假设这是一个错误..?
  • @LePiff 嗨,LePiff。谢谢你的意见。这不是一个错误。这是打印 unsigned int 的正确格式说明符,请参阅 here
  • 嗨云,感谢分享链接。我还有其他问题需要再次澄清您的第一个代码。无符号 n = (无符号) (*p - '0');如果变量 n 已经定义为无符号,那么 (unsigned) 的目的是什么?还有为什么要乘以 10U 而不是 10?这样做的目的是什么?再次感谢。
  • @LePiff 不客气!从技术上讲,它没有任何目的,因为转换将是隐式的。换句话说,演员表是可选的。我只是想明确表示它是“char - int”转换为unsigned int。 U 后缀表示它是unsigned integer constant。同样,只是为了真正明确地说明类型。演员表和后缀都可以省略,许多程序员都这样做,这也很好。通常,您不会在程序中看到这么多的转换/转换,但使用 chars 和 ASCII 值,您会看到。
  • 嗨云,我目前正在调试你的最后一行代码 long n = strtol(p, &end, 10);我想知道为什么 &end 的值等于繁忙数组中的最后一个字符,而不是找到第一个数字后最后一个数字“163”之后的第一个字符?再次感谢
【解决方案2】:

strspnstrcspn 可用于解析字符串。
可以使用strtol 代替sscanf 来获取号码。

#include <stdio.h>
#include <string.h>

int main ( void) {
    char busy[] = "this is; it was; 163; 234;";
    char *dlm = "0123456789";
    char *parse = busy;
    int number = 0;

    while ( *parse) {
        parse += strcspn ( parse, dlm);//count to next delimiter
        if ( 1 == sscanf ( parse, "%d", &number)) {
            printf ( "%d\n", number);
        }
        parse += strspn ( parse, dlm);//skip delimeters
    }

    return 0;
}

解析也可以去掉分号。
有些字段没有整数。

#include <stdio.h>
#include <string.h>

int main ( void) {
    char busy[] = "this is; it was; 163; 234;";
    char *dlm = ";";
    char *parse = busy;
    int number = 0;

    while ( *parse) {
        if ( 1 == sscanf ( parse, "%d", &number)) {
            printf ( "%d\n", number);
        }
        else {
            printf ( "could not parse integer\n");
        }
        parse += strcspn ( parse, dlm);//count to next delimiter
        parse += strspn ( parse, dlm);//skip delimeters
        //the above line will skip all consecutive delimiters
        //to process each delimiter use the line below
        //++parse;//skip one delimiter
    }

    return 0;
}

【讨论】:

  • 嗨,您共享的第二个代码,当您跳过第二个分隔符时,解析位置位于数组繁忙的空间中。 sscanf 如何知道不包含空格并且只读取整数直到分号?因为 sscanf 从空间位置开始,这会使你的 if 语句失败。
  • 只是添加代码确实有效,但我试图了解它的工作方式。再次感谢
【解决方案3】:

由于您有一个可修改的字符串,您可以使用strtok 将其分隔为基于; 分隔符的子字符串。如果子字符串是数字,则此代码会执行此操作。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void)
{
  char str[30] = {"this is; it was; 163; 234;;"};
  
  for(char* p=strtok(str, ";"); p!=NULL; p=strtok(NULL,str))
  {
    char* endptr;
    int i = strtol(p,&endptr,10);
    if(endptr != p)
    {
      printf("%d\n", i);
    }
  }
}

输出:

163
234

strtol 将“endptr”参数设置为指向字符串的开头以防万一失败,因此我们可以使用它来确定子字符串是否为数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2011-01-21
    • 2015-08-01
    相关资源
    最近更新 更多