每第 N 个单词插入字符串

Posted

技术标签:

【中文标题】每第 N 个单词插入字符串【英文标题】:Insert string every Nth word 【发布时间】:2016-07-12 20:30:25 【问题描述】:

在每第 N 个字符串之间添加字符串。

我的想法:

char *a = "one", *b = "two";

char *word = "Simple sentence containing some random words";
char result[200];


int len = strlen(word);
int spaces = 0;


for(int i = 0; i < len; i++)

    if(word[i] == ' ')
        spaces++;

    result[i] = word[i];

    if(spaces % 3 == 0)
    
        //copy a to result
    

    if(spaces % 4 == 0)
    
        //copy b to result
    


所以在我们准备好之后,结果应该是这样的:

Simple sentence containing one some two random words

我已经尝试过 strcpy、strcat 并且我已经为此苦苦挣扎了几天,但我似乎真的不明白这里的逻辑。如何进行?

【问题讨论】:

你需要一个不同的变量来索引result,而不是你用来索引word,因为在第一次插入之后,它们将不匹配。比如int j = 0; 这样result[j++] = word[i]; 然后尝试使用类似的技术复制ab 的每个字母。 【参考方案1】:

好的,这就是我想出的。代码的 cmets 中提供了我所做的一切的详细说明。

代码:

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

#define MAX_OUTPUT_LENGTH 200

int main(int argc, char const *argv[]) 
  /* You can replace the words defined below ("one" and "two") with any words
  * you want to insert at the given positions.
  */
  char one[] = "one";
  char two[] = "two";

  char sentence[] = "Longer but still simple sentence containing even more words";
  char result[MAX_OUTPUT_LENGTH];


  int len = strlen(sentence);
  int spaces = 0;
  int k = 0; //See Weather Vane's comment for why you also need the variable k
  int skipUntilAnotherSpace = 0;

  for(int i = 0; i < len; i++)
  
      if(sentence[i] == ' ') 
        spaces++;
        skipUntilAnotherSpace = 0; //See my explanation below for why this is done.
      

      if (k == 0) 
        result[i] = sentence[i]; //Normally, we can use the variable "i" until our insertion
       else 
        /* As Weather Vane's comment shows, after one insertion the positions you
        * need to grab from and insert to will change.  You cannot continue
        * to use "i". After the first insertion:
        * Sentence:
        * Simple sentence containing some random words
        *                            ^ position 27
        * Current value in result variable:
        * Simple sentence containing one [you want to insert here]
        *                                ^ position 31
        * So, we will need to insert into result at position k, and grab the info
        * from a different variable "i".
        */
        result[k] = sentence[i];
        //Increment k since it will not be incremented regularly in the for loop
        k++;
      
      if((spaces % 3 == 0) && spaces != 0 && skipUntilAnotherSpace == 0)
      
           int useVariableK = 0;
           if (spaces > 3) 
              /* Since spaces must already have been == 4, we have switched over
              to using variable K, so we must continue to do so */
              useVariableK = 1;
           

           if(!useVariableK) 
           result[i] = ' '; //Add a space before we add the word "one"
           i++; //Increment i since we added the spaces

           int j;
           for (j = 0; j < strlen(one); j++)  //Add the word "one"
             result[i + j] = one[j];
           
           //Increment the variable i the correct # of times since we added the word "one":
           i += (strlen (one));

           //Add a space after the word "one":
           result[i] = ' ';
           k = i + 1; //Set k = to i + 1 to account for the space we just added

           /* We need to revert back to where the variable "i" was before adding "one":

            We used the variable i to temporarily store the positions
            as we traversed across and added the word "one".  Then, we
            moved i back to the original position so we could access
            the correct position when using sentence[i] in the next iteration.

            Note that we need the +1 in the line below because we actually
            need to go back one more position than nessesary; when we re-enter
            the loop it will increment i to be +1 again! (sneaky)
           */
           i -= (strlen (one) + 1);

           /* Why we need the skipUntilAnotherSpace variable:
           We cannot simply increment the "spaces" variable after this; we need
           the number of spaces to conform to the number in the sentence, and
           just because we have more spaces in the result, it woudn't make sense
           to increment it for the sentence.

           However, if we leave it the same, then the next time we will enter
           this loop again since spaces == 3, and we don't want to enter this loop again;
           we have done our job already!

           So, we make sure not to enter the loop by setting the below variable
           to 1.  We do not enter the loop unless skipUntilAnotherSpace == 1.
           (If we even tried to increment the spaces variable, we would actually
            end up going into the next loop because spaces would = 4 ;) )

            Finally, we switch back skipUntilAnotherSpace to be 0 once
            another space is detected in the sentence.
           */
           skipUntilAnotherSpace = 1;
          else 
           //Use variable K like we do if spaces == 4:
           /* Most of this loop is exactly identical to the previous one, except
           that we don't need another space since it was already added before when
           "one" was inserted, and we use the variable "k" instead of i. */
           int j;
           for (j = 0; j < strlen(one); j++) 
             result[k + j] = one[j];
           
           k += (strlen (one));
           result[k] = ' ';
           k += 1;

           //spaces++;
           skipUntilAnotherSpace = 1;
         
      

      if((spaces % 4 == 0) && spaces != 0 && skipUntilAnotherSpace == 0)
      
         /* Most of this loop is exactly identical to the previous one, except
         that we don't need another space since it was already added before when
         "one" was inserted, and we use the variable "k" instead of i. */
         int j;
         for (j = 0; j < strlen(two); j++) 
           result[k + j] = two[j];
         
         k += (strlen (two));
         result[k] = ' ';
         k += 1;

         //spaces++;
         skipUntilAnotherSpace = 1;
      

  

  printf("%s.\n", result);
  return 0;

注意:看Weather Vane's这个问题的评论可以进一步理解为什么变量k是必须的(我在cmets里也有解释过,就是觉得Weather Vane的版本有点更简洁)。

这段代码产生的输出是:

更长但仍然是一个简单的两个句子,其中包含一个甚至更多的两个单词。

如果您已将变量 onetwo 分别更改为值 "hello""goodbye",代码仍然可以正常工作并生成:

更长但仍然 hello 简单的再见句子包含 hello 甚至更多的再见词。

基本上,代码每三个单词插入变量one[]中的值,每四个单词插入变量two[]中的值。

我希望这会有所帮助!

【讨论】:

好的,这让我开始了。但是,如果句子有更多的单词,输出将是不正确的。对于整个句子,它应该是每第 n 个单词 - 而不仅仅是前 3 个单词和第 4 个单词。如何进行?我没能成功。 @jaked:只要有足够的空间用于输出结果,您可以将句子更改为任何内容。例如,我将我的句子改为char sentence[] = "Another random sentence containing other random stuff"。输出运行良好,并且不正确(句子有更多单词)。使用这种方法,我还能够在句子中插入两个词任何其他地方。例如,我将第一个和第二个循环中的spaces == 3spaces == 4 更改为spaces == 2spaces == 5。输出看起来不错:Simple sentence one containing some random two words. @jaked:也许我误解了你的问题? 我的意思是如果输入是:Longer but still simple sentence containing more words,输出是:Longer but still WORD1 simple WORD2 sentence containing more WORD1 words 啊,我明白了。我将研究通过这种方法使用模运算符。【参考方案2】:

逐个字符处理字符串并计算空格(只要您聚合空格等)并没有错,但是,还有另一种方法可以考虑更多的灵活性。您可以使用strtok(在string.h)来标记您的输入字符串,而不是搜索空格。然后,只需计算 tokens(单词)并将添加的内容作为第 n 个单词(或单词)插入到适当的位置(索引)。

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

enum  MAXC = 512 ;

int main (void) 

    char *w1 = "one", *w2 = "two";              /* replacement words   */
    int nth1 = 3, nth2 = 4;                     /* positions for w1/w2 */
    char line[MAXC] = "", *p = NULL, *delim = " \t.,;\n";
    char *fmt1 = "%s", *fmt2 = " %s";

    while (fgets (line, MAXC, stdin))  /* for each line read from stdin */
        int idx = 0;                        /* tokenize line with strtok */
        for (p = strtok (line, delim); p; p = strtok (NULL, delim)) 
            printf (!idx ? fmt1 : fmt2, p); idx++;    /* print token */
            if (idx == nth1) printf (fmt2, w1);   /* check and insert w1 */
            if (idx == nth2) printf (fmt2, w2);   /* and w2 in nth pos   */
        
        putchar ('\n');
    

    return 0;

(注意:您可以根据需要定制索引。例如,您可以在插入第 nth 个单词后增加索引 idx 以让它们按顺序插入等...)

使用/输出示例

$ echo "Simple sentence containing some random words" | ./bin/replacenthword
Simple sentence containing one some two random words

由于您没有对要操作的字符串进行硬编码,因此您现在可以在发送它的任何行中替换 nth1nth2 单词,如果您在整个文件中比如,例如

输入文件示例

$ cat dat/replcmt.txt
Simple sentence containing some random words
A quick brown fox jumps over the lazy dog
Fewer words
That's all folks

示例使用/输出带文件

$ ./bin/replacenthword <dat/replcmt.txt
Simple sentence containing one some two random words
A quick brown one fox two jumps over the lazy dog
Fewer words
That's all folks one

如果你只想插入第nth个单词如果有后面的单词,那么你需要做的就是改变每个token的测试和打印顺序。

    while (fgets (line, MAXC, stdin))  /* for each line read from stdin */
        int idx = 0;                        /* tokenize line with strtok */
        for (p = strtok (line, delim); p; p = strtok (NULL, delim)) 
            if (idx == nth1) printf (fmt2, w1);   /* check and insert w1 */
            if (idx == nth2) printf (fmt2, w2);   /* and w2 in nth pos   */
            printf (!idx ? fmt1 : fmt2, p); idx++;        /* print token */
        
        putchar ('\n');
    

这将产生相同的输出,但如果行中出现nth1 或更少的标记(单词),则省略替换,例如

$ ./bin/replacenthword <dat/replcmt.txt
...
That's all folks

查看所有答案,如果您有任何问题,请告诉我。

【讨论】:

以上是关于每第 N 个单词插入字符串的主要内容,如果未能解决你的问题,请参考以下文章

每第n个字符拆分字符串?

在其中每第 n 次出现时反转一个字符串[关闭]

将字符串格式化为仅在 python 中的单词之间有 n 个空格

如何拆分Python列表每第N个元素

每第 n 个范围递增 R

XSLT 将每第 n 个项目分组到新组中