0

Currently I'm trying to take a binary string, say 100101010, and split it into groups of three, so 100 101 010. Here's what I've written so far, for some reason it only prints the first group, 100 and then nothing after that.

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

int main(){

    int i;
    char *line = NULL;

    free(line);
    scanf("%ms", &line);

    printf("%d\n", strlen(line));

    for(i=0; i < strlen(line); ++i) {

        if ( i % 3 == 0 ){
            sprintf(line, "%c%c%c", line[i],line[i+1],line[i+2]);
            printf(line);
        }

    }

}
3
  • Why are you freeing a NULL pointer? Commented Oct 28, 2015 at 0:00
  • Not really a terrible thing to do. Nothing actually happens if you free a null pointer. Commented Oct 28, 2015 at 0:07
  • 1
    True, I know it's harmless, but the line right before the free says line = NULL, so it's pointless. Why include pointless code - it makes the real problems harder to spot... BTW - you don't actually free line at the end, so you have a free where you don't need it and are missing one where you do ;-) Commented Oct 28, 2015 at 0:09

2 Answers 2

2

sprintf(line, "%c%c%c", line[i],line[i+1],line[i+2]); writes your 3 characters into line, and so you overwrite your original string with your first group of 3. This means the next time through the loop i(4) is > strlen(line)(3) and so the loop stops.

Try:

/* Since 'line' and it's contents doesn't change in the loop we can
 * avoid the overhead of strlen() calls by doing it once and saving the
 * result.
 */
int len = strlen(line);

/* As mentioned in the comments, you could do
 * for(i = 0; i < len; i+=3) and then you don't need the
 * if (i%3) check inside the loop
 */
for(i=0; i < len; ++i) {
    if ( i % 3 == 0 ){
        /* This could be refactored to a loop
         * or scanf() to a different string but I say scanf is overkill
         * in this scenario...
         */
        char buffer[4];
        buffer[0] = line[i];
        buffer[1] = line[i+1];
        buffer[2] = line[i+2];
        buffer[3] = '\0';
        printf("%s\n", buffer);
        // Or just use puts() since we're not really doing 
        // any formatting.
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

That worked great, thanks! For clarification, combining the string within the loop made strlen smaller each time which made it only run once?
Yes. scanf(line... changed the contents of line and so strlen returned a different value. I'll edit another comment above.
why not do for(i = 0; i < strlen(line); i+=3 )? That would get rid of the if ( i % 3 == 0 ) condition.
@druciferre - +1 from me. That's even better. In my defense I try to keep things like this close to the OP's code (i.e. not changing too much at once)
@John3136: I might suggest a small edit to your otherwise correct and clear answer: In general printf should not be given "uncontrolled" values for its first argument. The reason is that the real-world implementation of printf() might balk at trying to figure out a FORMAT string like " % " that could end up being in the original line. Simply substitute fputs(buffer, stdout) and you're fine. In my experience newlib's implementation did crash when there was a % followed by a space at the end of the format string.
|
0

strlen(line) is reevaluated on each pass through the for loop, and you're changing the data that line points to inside the for loop by calling sprintf. Your sprintf makes line a 3-character string, hence you get only one trip through the loop in which i%3 is zero.

Comments

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.