【问题标题】:Create a string from char array in C从C中的char数组创建一个字符串
【发布时间】:2014-11-12 14:30:29
【问题描述】:

我有一段代码循环遍历一个 char 数组字符串以尝试检测单词。它循环遍历,如果检测到 A - Z 或 a - z 或 _(下划线),它将把它添加到 char 数组中。因为它们是单词,所以我需要的是能够将它们放入一个字符串中,然后我可以使用另一个函数进行检查,然后可以将其丢弃。 这是我的功能:

char wholeProgramStr2[20000];
char wordToCheck[100] ="";

IdentiferFinder(char *tmp){
    //find the identifiers
    int count = 0;
    int i;
    for (i = 0; i < strlen(tmp); ++i){
        Ascii = toascii(tmp[i]);
        if ((Ascii >= 65 && Ascii <= 90) || (Ascii >= 97 && Ascii <= 122) || (Ascii == 95))
        {
            wordToCheck[i] = tmp[i];
            count++;
            printf("%c",wordToCheck[i]); 
        }
        else {
            if (count != 0){
            printf("\n");
        }
            count = 0;
        }
    }
    printf("\n");
}

目前我可以看到所有单词,因为它将它们打印在不同的行上。

WholeProgram2 的内容是文件的所有行。它是 *tmp 参数。

谢谢。

【问题讨论】:

  • 永远不要与幻数比较。使用isalpha()'-'
  • 您的问题类似于this one,与that 重复。在此处根据您的需要调整 my answer
  • 您当前已经填充了wordToCheck 数组(但删除了="" 初始化器,全局变量为zero initialized,因此您将在数组中获得一个以NUL 结尾的字符串,因为tmp 是不要太长。)它是一个全局变量,您可以从其他函数访问它。请说明您想要什么或问题是什么。
  • Ascii = toascii(tmp[i]); 到底是什么? Ascii 在哪里定义?它的类型是什么?
  • 你能解释一下你用什么分隔符来解析来自wholeProgramStr2的单词。通常,空格、制表符等用作此类解析的分隔符。这是你在做什么?

标签: c arrays string char


【解决方案1】:

您描述了将大字符串分解成小字符串(单词)。
假设您使用普通分隔符进行解析,例如空格或制表符或换行符:

这是一个三步方法
首先,获取有关您的源字符串的信息。
第二,动态创建目标数组以满足您的大小需求
第三,继续循环strtok() 填充您的目标字符串数组(char **)

(第四个是释放创建的内存,您需要这样做)
提示:原型可能如下所示:
// void Free2DCharArray(char **a, int numWords);

代码示例:

void FindWords(char **words, char *source);
void GetStringParams(char *source, int *longest, int *wordCount);
char ** Create2DCharArray(char **a, int numWords, int maxWordLen);
#define DELIM " \n\t"

int main(void)
{
    int longestWord = 0, WordCount = 0;
    char **words={0};
    char string[]="this is a bunch of test words";

    //Get number of words, and longest word, use in allocating memory
    GetStringParams(string, &longestWord, &WordCount);

    //create array of strings with information from source string
    words = Create2DCharArray(words, WordCount, longestWord);

    //populate array of strings with words
    FindWords(words, string);

    //Do not forget to free words (left for you to do)
    return 0;   
}

void GetStringParams(char *source, int *longest, int *wordCount)
{
    char *tok;
    int i=-1, Len = 0, KeepLen = 0;
    char *cpyString = 0;
    cpyString = calloc(strlen(source)+1, 1);
    strcpy(cpyString, source);
    tok=strtok(source, DELIM);
    while(tok)
    {
        (*wordCount)++;
        Len = strlen(tok);
        if(Len > KeepLen) KeepLen = Len;
        tok = strtok(NULL, DELIM);
    }
    *longest = KeepLen;
    strcpy(source, cpyString);//restore contents of source
}

void FindWords(char **words, char *source)             
{
    char *tok;
    int i=-1;

    tok = strtok(source, DELIM);
    while(tok)
    {
        strcpy(words[++i], tok);
        tok = strtok(NULL, DELIM);
    }
}

char ** Create2DCharArray(char **a, int numWords, int maxWordLen)
{
    int i;
    a = calloc(numWords, sizeof(char *));
    if(!a) return a;
    for(i=0;i<numWords;i++)
    {
        a[i] = calloc(maxWordLen + 1, 1);       
    }
    return a;
}

【讨论】:

    【解决方案2】:

    如果您的目标是在字符数组中查找单词,您可能希望首先找到一个有效的字符序列(并且您似乎正在尝试这样做),并且一旦找到 一个,进行二次检查以了解它是否是一个真实的单词。如果它确实是一个词,那么您可能会决定保留它以供进一步使用。

    这种方法的优点是您不需要保留大量潜在单词的缓冲区,您只需要一个大小与字典中最大单词匹配的固定缓冲区。实际上,您甚至可能不需要缓冲区,而只需要一个沿着 char 数组滑动的指针,指向一个可能的单词的开头,以及一个 int(尽管一个字节可能就足够了)来跟踪该单词的长度。

    // structure to store a word match in array
    typedef struct token_s {
      int length;
      const char *data;
    } token_t;
    
    void nextToken(const char *tmp, int len, token_t *to){
      char *start = NULL;
      while (len){
        if (start) {
          // search for end of current word
          if (!isalpha(*tmp)) {
            to->data = start;
            to->length = tmp - start;
            return;
          }
        } else { 
          // search for beginning of next word
          if (isalpha(*tmp))
            start = tmp;
        }
        tmp++;
        len--;
      } // while
      if (start) {
        to->data = start;
        to->length = tmp - start;  
      }
    }
    

    简单通过:

    • char 数组的开头,或者to-&gt;data + to-&gt;length + 1,如果它没有超出数组的结尾
    • 要扫描的字符数组的下雨长度
    • 指向归零token_t 的指针

    每次调用nextToken,并检查令牌的内容以了解它是否找到了候选人;如果没有,您就知道阵列已被完全扫描。

    void scanArray(const char *tmp, int len){
      while (len > 0){
        token_t to;
        to.data = NULL;
        to.length =0;
        nextToken(tmp, len, &to);
        if (to.data) {
          tmp += to.length +1;
          len -= to.length +1;     
          // process token here...
        } else break;
      } // while
    }
    

    我使用isalpha 来测试有效字符,但您需要用自己的函数替换它。您必须在scanArray 的正文中插入自己的代码以进行二次检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      • 2021-07-19
      相关资源
      最近更新 更多