6

I have a trouble with my C-code. My input is a string. The calculator has to count how many times the first character in the string repeats until it finds another different character and write down the number of times it appears and the character it considers. Then it starts again considering the next character. The following example might clear you:

  1. If the input is RRDDuuuRRRuuu, the output must be 2R 2D 3u 3R 3u.

I cannot (and I do not want to) use too many indices, but I do not manage to find a solution using few indices.

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

int main()
{
    char str1[3000]; // Declaring string arrays
    int i, j; // Declaring variables for length, iteration, counts
    long unsigned int n;
    
    printf("Enter a string: ");
    
    scanf("%s", str1); // Inputting a string from the user
    
    printf("Its first character is %c\n", str1[0]);
    
    n = strlen(str1);
    
    printf("String length is %lu\n", n);
    
    i = 0;
    do { i++; } while (str1[i] == str1[0]);
    printf("%d%c ", i, str1[0]);
    j = i - 1;
    do { j++; } while (str1[j] == str1[i]);
    printf("%d%c ", j - i, str1[i]);
    
    return 0;
}
4
  • 3
    Hint: use a single loop, and compare the current character to the prior one. Commented May 25 at 0:12
  • Thx, but like so for (i=0;i++;i<n){ if (str1[i]==str1[i+1]) i++; else printf("%d%c ",i,str1[i]); } my code is wrong. Why? Thx again. Commented May 25 at 0:21
  • What if your input contains spaces? You should use fgets. Commented May 25 at 10:04
  • Thanks for your comment, but my input does not contain spaces. However, I would be curious to know what the C code would look like if the input did contain spaces. Commented May 25 at 13:09

4 Answers 4

8

This will only be able to count the first two characters:

i=0;
do {i++;} while (str1[i]==str1[0]);
printf("%d%c ",i,str1[0]);           // first
j=i-1;
do {j++;} while (str1[j]==str1[i]);
printf("%d%c ",j-i,str1[i]);         // second

You need to keep going until the end of the string. You however don't need a separate index for each character. Just loop around each character counting.

Example:

void print_rep(const char *str) {
    while (*str) {                   // while not at the null terminator
        unsigned count = 0;          // init count
        const char ch = *str;        // save the character
        do {
            ++count;                 // increase the count
            ++str;                   // step pointer to the next character
        } while(*str == ch);         // loop until a new character is found
        printf("%u%c ", count, ch);  // print result
    }                                // go back to count the next character
    putchar('\n');
}

Demo

Sign up to request clarification or add additional context in comments.

Comments

4

You are thinking too hard. :-) Here is help to think it through. You only need a single index into the string, plus two pieces of information: current character and count.

So, given the string “RRDDuuuRRRuuu”:

Start with the first character, R. That is your current character.

Loop through the string, counting the number of times you find R.

RRDDuuuRRRuuu
^
current = 'R'
count   = 1
RRDDuuuRRRuuu
 ^
current = 'R'
count   = 2
RRDDuuuRRRuuu
  ^
oh no! we have found a DIFFERENT character!

At this point, we know we found two Rs. Print it.
Then set the current character to the new character (D) and reset your count to one, then let the loop continue as before.

RRDDuuuRRRuuu
  ^
current = 'D'
count   = 1
RRDDuuuRRRuuu
   ^
current = 'D'
count   = 2
RRDDuuuRRRuuu
    ^
new character again

Stop when the new current character would be a \0.

RRDDuuuRRRuuu
             ^
um, new character would be '\0', so after printing the “3u” we are done.

Good luck!

EDIT: Well, since everyone is just posting solutions, once you have done your own you can look at the code for mine.

#include <stdio.h>

void solution(const char * s)
{
  char current = s[0];
  int  count = 1;
  while (*s++)
  {
    if (*s == current)
    {
      count += 1;
    }
    else
    {
      printf("%d%c ", count, current);
      current = *s;
      count = 1;
    }
  }
  puts("");
}

int main(int argc, char ** argv)
{
  if (argc == 2)
    solution(argv[1]);
  return 0;
}

Linux:

$ clang -Wall -Wextra -Werror -pedantic-errors -O3 a.c
$ ./a.out RRDDuuuRRRuuu
2R 2D 3u 3R 3u
$ ./a.out abb
1a 2b
$ ./a.out aab
2a 1b
$ ./a.out a
1a
$ ./a.out ""

$ ./a.out
$ █

Windows:

C:> cl /nologo /EHsc /Ox a.c
a.c
C:> a.exe RRDDuuuRRRuuu
2R 2D 3u 3R 3u
C:> a.exe abb
1a 2b
C:> a.exe aab
2a 1b
C:> a.exe a
1a
C:> a.exe ""

C:> a.exe
C:> █

3 Comments

Thx, but with "int count=1; for (i=0;i++;i<n) { if (str1[i]==str1[i+1]) count++; else { printf("%d%c ",count,str1[i]); count=1; } }" my output is not I desired. Why? Thx again
I do not understand why it prints nothing. Sorry, but I am not good with programs
@Puck You have swapped condition and incrementer of the loop, I had to run the code myself to see it. Your condition is i++, which for i=0 results in 0, so you never enter the loop. Making it a for(i=0;i<n;i++) has the code working exactly as expected, good job!
0

Your program only handles the first 2 characters, assuming there are at least 2 sets of characters. It will have undefined behavior if the string only has a single character, repeated or not.

You should wrap the counting loop in an outer loop that repeats until the end of the string.

Note also these problems:

  • tell scanf the maximum number of characters to store into the destination array to avoid a buffer overflow on longer input

  • check the return value of scanf() to detect invalid or missing input.

  • always append a newline at the end of your output.

  • j = i - 1; is cumbersome and works by coincidence. j = i is more consistent with your do/while loop logic.

    IMHO you should avoid do/while loop completely. These constructions are notoriously error prone and lead to confusing code, and many logical bugs. Use for or while loops instead.

Here is a modified version:

#include <stdio.h>

int main(void)
{
    char buf[3000];  // Declaring string arrays
    
    printf("Enter a string: ");
    fflush(stdout);  // ensure the prompt is visible to the user
    if (scanf("%2999s", buf) != 1) {
        printf("input error\n");
        return 1;
    }

    const char *p = buf;
    while (*p) {
        int count = 1;
        char ch = *p++;
        while (*p == ch) {
            count++;
            p++;
        }
        printf("%d%c ", count, ch);
    }
    putchar('\n');
    return 0;
}

Comments

0

The only two vars you need - char counter and pointer for iterations or index (with pointer less text).

There's enough one loop with comparing current char with next and exit loop on '\0' char;

#include <stdio.h>

int main() {
    char str1[3000];
    char *c = str1;
    printf("Enter a string: ");
    if(scanf("%2999s", str1) != 1) return 1; //Protect from overflow and empty
    for (int n = 1; *c; c++,n++)
        if (*c != *(c+1)){
            printf("%d%c ", n, *c);
            n=0;
        }
    return 0;
}

https://godbolt.org/z/nq1z1qqMa

8 Comments

n^=n isn't necessarily the fastest way to assign zero to a variable and using xor isn't necessarily the fastest when comparing for equality. Better use the assignment operator and equality operator and let the compiler pick what's appropriate for the target CPU.
Microoptimizations like this XOR stuff is a bad idea, especially when teaching to beginners.
In most cases compiler will do the same. I wanted just to show this trick. But you are right, this is not a good idea for beginners. Thanks.
@Solt It will usually pick what's fastest. If that is doing an xor or storing 0 depends on architecture. You may even see your xor being compiled into a load of 0.
Yes, I know, I even read topics like this stackoverflow.com/questions/7695309 I just only wanted to show the idea. For compare by reference it could be even worse. When I was young I liked to learn such a tricks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.