将字符串过滤为C中的合法字符串

时间:2017-05-05 08:30:18

标签: c string int

我正在写一个程序。传入的字符串就像这个*H1W000500,这是一个合法的字符串,我将*H1W之后的字符串内容复制到整数类型。

但是如果字符串不合法,我想过滤掉这个字符串。例如000500*H1W.....,如果字符串不合法,请不要复制内容并跳过。如果字符串是合法的,则仅复制内容。

这里我正在做什么,但每当有不相关的字符串时,它会复制零值,这是不可取的。

*H1W~@#$

3 个答案:

答案 0 :(得分:1)

您已接近,但使用strstr可以更好地表达您对strncmp的使用情况,以便比较4的第一个receiveddata字符。 (如果您的目标字符串位于receiveddata的中间,那么strstr就可以了)您还需要对strtoul转换提供错误检查。将这些部分放在一起你可以做类似下面的事情(注意:这是针对单个值显示的,在循环中,如评论中所述,将return更改为continue

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

/* declare constants, avoid magic number use in code */
enum { PRE = 4, BASE = 10, MAX = 50 };

int main (void) {

    char receiveddata[MAX] = "*H1W000500", *p = NULL;
    unsigned long head1weight;

    if (strncmp (receiveddata, "*H1W", PRE) != 0)   /* cmp 4 chars */
        return 1;   /* you would continue here */

    if (strlen (receiveddata) <= PRE)               /* more chars exist? */
        return 1;   /* you would continue here */

    errno = 0;  /* set errno to known value */
    head1weight = (unsigned)strtoul (&receiveddata[PRE], &p, BASE);

    /* check for error conversions on conversion */
    if ((errno == ERANGE && (head1weight == ULONG_MAX)) || 
        (errno != 0 && head1weight == 0)) {
        perror ("strtoul");
        return 1;   /* you would continue here */
    }

    if (&receiveddata[PRE] == p) {  /* check if chars converted */
        fprintf (stderr, "No digits were found\n");
        return 1;   /* you would continue here */
    }

    printf ("head1weight : %lu\n", head1weight);

    return 0;
}

示例使用/输出

$ ./bin/parsetounsigned
head1weight : 500

仔细看看,如果您有其他问题,请告诉我。

(注意:C通常避免使用MixedCasecamelCase变量名来支持所有小写,保留所有大写以用于常量和宏。它是样式,所以这完全取决于你......)

答案 1 :(得分:0)

来自strtoul上的Linux手册页。

  

如果根本没有数字,strtoul()将nptr的原始值存储在* endptr中(并返回0)。

因此,如果在strtoul之后,ptr与起始指针相同,则表示没有合法字符。

char* ptr;

unsigned long Head1Weight = strtoul(p + 4, &ptr, 10);
if (ptr == p + 4)
{
    // There were no digits
}
else if (strlen(ptr) > 0)
{
    // There were characters in the string after the end of the number
}

答案 2 :(得分:0)

OP的p = strstr(ReceivedData, "*H1W"); if(p) {在通过strstr("abcd12*H1W", "*H1W")时不够,虽然它是一个开始。

OP的验证目标不够具体。 “* H1W之后的字符串内容,即000500到整数类型。”

  1. “+ 123”,“ - 123”,“123”评估为整数,是否有效?

  2. “123”可以评估为整数,是否有效?

  3. 示例暗示数字部分应该正好是6位小数,但这是不确定的。

  4. 示例代码使用unsigned,可能是16位吗?只有“000000”到“065535”有效吗?

  5. “ - 123”通过strtoul()转换成功,对此目标有效吗?

  6. 这应该通过“* H1W000500xyz”吗?是允许还是忽略额外的文字?

  7. 这是编写代码中的常用,因为规范最初有解释问题,然后趋于发展。

    代码应该允许进化。

    让我们从*H1W开始,接着是sscanf()的正好6位小数。检查数字后,下面的代码使用"%n"来记录扫描位置。如果PREFIX包含%,则此方法需要额外的工作。

      // PREFIX should not contain %
      #define PREFIX "*H1W"
      #define DIGIT_FMT "%*[0-9]"
      #define VALID_LENGTH 10
    
      char ReceivedData[50];
      unsigned long Head1Weight = 0;
    
      int n = 0;
      sscanf(ReceivedData, PREFIX DIGIT_FMT "%n", &n);
    
      if (n == VALID_LENGTH && ReceivedData[VALID_LENGTH] == '\0') {
        Head1Weight = strtoul(ReceivedData + sizeof PREFIX - 1, NULL, 10);
      }