0

I need to read a PPM file but I'm limited to only using getchar() but I'm running into trouble ignoring whitespaces.

I'm using num=num*10+(ch-48); to read the height and width but don't know how to read them all at once while ignoring spaces and '\n' or comments.

I use this to read the magic number:


int magic;
while(magic==0){
if (getchar()=='P')     //MAGIC NUMBER
magic=getchar()-48;
}
printf("%d\\n",magic);

i used this function to read the height and width which works only when the data in the header is seperated only by '\n'


int getinteger(int base)
{ char ch;
int val = 0;
while ((ch = getchar()) != '\\n' && (ch = getchar()) != '\\t' && (ch = getchar()) != ' ')
if (ch \>= '0' && ch \<= '0'+base-1)
val = base\*val + (ch-'0');
else
return ERROR;
return val;
}

this is the part in main()

height=getinteger(10);
    while(height==-1){
        height=getinteger(10);
    }
1
  • 1
    Welcome to SO. Does your compiler mention something about multi-character literals when it sees '\\n'? Why do you escape the backshlash? Commented Dec 1, 2022 at 10:59

1 Answer 1

1

Comparing "magic" with 0 is undefined behaviour since it's not initialized yet (so it's basically just a chunk of memory):

int magic;              // WARNING: We don't know exact value, may be not 0
while(magic==0){
if (getchar()=='P')     //MAGIC NUMBER
magic=getchar()-48;
}

Consider initializing variable before comparing:

int magic = 0;            // We know that magic will be defined as 0
while (magic == 0) {
    if (getchar() == 'P') // MAGIC NUMBER
        magic = getchar() - 48;
}

In this function:

int getinteger(int base)
{ char ch;
int val = 0;
while ((ch = getchar()) != '\\n' && (ch = getchar()) != '\\t' && (ch = getchar()) != ' ')
if (ch \>= '0' && ch \<= '0'+base-1)
val = base\*val + (ch-'0');
else
return ERROR;
return val;
}

(I'm assuming that ERROR = -1, is that correct?) In your condition getchar() will work 3 times, not 1 (since it calls getchar() for putting in ch every check). Rewrite it to call only once for saving in variable ch. Another problem occurs when first symbol will be whitespace, not digit. In this case val will remains 0 (since while loop will be skipped), so returned value will also be '0'. To avoid this, you can check value of val and return ERROR, when it is not changed:

int getinteger(int base) {
    char ch = getchar(); // get only one char and save for later use
    int val = 0; // 0 means not changed
    while (ch != '\n' && ch != '\t' && ch != ' ') {
        if (ch >= '0' && ch <= '0' + base - 1)
            val = base * val + (ch - '0');
        else
            return ERROR;
        ch = getchar(); // get a new char for next loop iteration and checking if it is digit
    }
    if (val == 0) // val was not changed
            return ERROR; // loop in "main" will be continued
    else
            return val; // val was changed, return it
}

UPD: We can also use this fact to simplify our function a lot:

int getinteger(int base) {
    char ch = getchar(); // get only one char and save for later use
    int val = 0; // 0" means not changed
    while (ch >= '0' && ch <= '0' + base - 1) { // if "ch" is not a number, this loop will be skipped
            val = base * val + (ch - '0');
            ch = getchar(); // get a new char for next loop iteration and checking if it is digit
    }

    if (val == 0) // val was not changed (ch was not a number)
        return ERROR; // loop in "main" will be continued
    else
        return val; // val was changed, return it
}

And last but not least, remove extra '' before symbols (\\n -> \n, \>= -> >= etc.) if they present in your code.

Combining everything above results in something like this:

#include <stdio.h>

#define ERROR -1

int getinteger(int base) {
    char ch = getchar(); // get only one char and save for later use
    int val = 0; // 0 means not changed
    while (ch >= '0' && ch <= '0' + base - 1) { // if "ch" is not a number, this loop will be skipped
            val = base * val + (ch - '0');
            ch = getchar(); // get a new char for next loop iteration and checking if it is digit
    }

    if (val == 0) // val was not changed (ch was not a number)
        return ERROR; // loop in "main" will be continued
    else
        return val; // val was changed, return it
}

int main() {
    // dunno what's before
    int magic = 0; // We know that magic will be defined as 0
    while (magic == 0) {
        if (getchar() == 'P') // MAGIC NUMBER
            magic = getchar() - 48;
    }
    printf("magic = %d\n", magic);

    int height = getinteger(10);
    while (height == -1)
        height = getinteger(10);
    printf("height = %d\n", height);
    // dunno what's after
}

Result:

$ echo "   \n  P3 #blabla \n  34  \t " | ./a.out
magic = 3
height = 34
Sign up to request clarification or add additional context in comments.

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.