mary
mary

Reputation: 79

how to change a word in a string by its number?

I have this assignment:

Replace the numbered word in the sentence with three characters: ???

The problem is I can't replace the whole word by its number, my program changes only 3 first characters.

Here is my code:

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

int main() {
    char sentence[100];
    int word_number;
    int pos;
    int i;

    printf("Enter sentence: ");
    fgets(sentence, 100, stdin);

    printf("Enter word number: ");
    scanf("%d", &word_number);

    pos = 0;
    for (i = 0; i < strlen(sentence); i++) {
        if (sentence[i] == ' ') {
            word_number--;
        }

        if (word_number == 1) {
            pos = i;
            break;
        }
    }

    // Update the sentence
    sentence[pos] = '?';
    sentence[pos + 1] = '?';
    sentence[pos + 2] = '?';

    printf("Result sentence: %s\n", sentence);

    return 0;
}

Upvotes: 1

Views: 99

Answers (2)

D&#250;thomhas
D&#250;thomhas

Reputation: 10093

I’m not sure I’d try to do this in-place. For small data, it doesn’t hurt to just create a new buffer, even if it is just a temporary.

But, since we are posting solutions, here’s a single-pass version:

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

void replace_nth_word_with( char * dest, int n, const char * src, const char * word )
{
  char last = ' ';
  while (*src)                                     // For each character in src:
    if ((*src != ' ') and (last == ' ') and !n--)  //   If we found a word-begin AND it is the Nth word:
    {                                              //
      for (size_t k = 0;  word[k];  k++)           //     Copy the new word to dest
        *dest++ = word[k];                         //
      while (*src and (*src != ' ')) ++src;        //     Skip the old word in src
    }                                              //
    else                                           //   Otherwise just copy the character over
      last = *dest++ = *src++;                     //
  *dest = '\0';                                    // End of string
}

void ask_string( const char * prompt, char * s, size_t n )
{
  printf( "%s", prompt );
  fgets( s, (int)n, stdin );
  char * p = strpbrk( s, "\n\r" );
  if (p) *p = '\0';
}

void ask_int( const char * prompt, int * n )
{
  char s[20];
  printf( "%s", prompt );
  fgets( s, sizeof s, stdin );
  *n = strtol( s, NULL, 10 );
  // It hurts to write this without error checking, LOL
}

int main(void)
{
  char sentence[1000];
  ask_string( "Sentence? ", sentence, sizeof sentence );

  int word_number;
  ask_int( "Word number (counting from 1)? ", &word_number );

  char new_word[100];
  ask_string( "New word? ", new_word, sizeof new_word );

  char new_sentence[sizeof sentence + sizeof new_word];
  replace_nth_word_with( new_sentence, word_number-1, sentence, new_word );

  printf( "\"%s\"\n", new_sentence );
  return 0;
}

Upvotes: 1

chqrlie
chqrlie

Reputation: 145277

There are multiple issues in the code:

  • Your approach only works if the word to be replaced has exactly 3 letters. For longer or shorter words, you need to move the contents of the remainder of the string.

  • Another restriction in your code is you assume that words a separated by a single space, which may of may not be explicitly stated in the assignment.

  • Similarly, you assume the n-th word is followed by a space, which may not be the case if the word is the last one in the sentence.

  • you should check the return values of fgets() and scanf() to detect invalid or missing input.

Here is a modified version.

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

int is_sep(char cc) {
    // separators are space, newline and the null byte
    return (cc == ' ' || cc == '\n' || cc == '\0');
    // you could also accept punctuation as word separators:
    //return strchr(" \t\n.,:;?!'`"@#$%^&*()[]{}<>/`~+=|", cc);
}

int main() {
    char sentence[200];
    int word_number;

    printf("Enter sentence: ");
    // read a sentence, allow for 2 extra bytes to insert replacement
    if (!fgets(sentence, sizeof(sentence) - 2, stdin))
        return 1;

    printf("Enter word number: ");
    if (scanf("%d", &word_number) != 1)
        return 1;

    int len = strlen(sentence);
    int start = 0;
    int wn = 1;
    char last = ' ';
    for (int i = 0;; i++) {
        char cc = sentence[i];
        if (is_sep(cc)) {
            if (!is_sep(last)) {
                /* end of word */
                if (wn == word_number) {
                    // replace this word with `???`
                    memmove(sentence + start + 3, sentence + i, len + 1 - i);
                    memcpy(sentence + start, "???", 3);
                    break;
                }
                wn++;
            }
        } else {
            if (is_sep(last)) {
                /* start of a word */
                start = i;
            }
        }
        last = cc;
        if (cc == '\0')
            break;
    }
    printf("Result sentence: %s\n", sentence);
    return 0;
}

Upvotes: 1

Related Questions