Use scanf() to read n in a loop?

I must use scanf() to read each 2-digit hexadecimal value. Each 2-digit
hexadecimal number will be separated by a single space and a ‘n’ character (rather
than a space after the number) will indicate that the message is complete. Your program should scan through every value until either you have read in maxium number of inputs or you have reached to the end of line. The maxium number of inputs are 5.

For example, a valid input might be: 00 4A 12 BB 43 88

Another valid input will be: AA BB 33 12(n)

If i have my number of inputs greater than or equal to MAX_CHAR_LENGTH, it will work fine. However, it seems to not able to work when the number of inputs are smaller than that. Is there a way to detect whether curr_hex is n or not so I could break out?

This is what I had for my program

#include <stdio.h>
#define MAX_CHAR_LENGTH 5
int main() {

    unsigned int curr_hex;
    
    printf("enter hex values: " ); // prompt user to enter hex values
    
    for (int i = 0; i < MAX_CHAR_LENGTH && !(curr_hex == 'n'); i++) { 
    scanf("%x", &curr_hex);
    printf("Read hex: 0x%02Xn", curr_hex);
    }
    return 0;
}

11

scanf() will only return input when encountering 'n' or EOF (on Linux can generate an EOF on stdin by by pressing ctrl-d once or twice).

The format string %x will skip any leading white space and accept any number of digits so I don’t think you can get away with using it (you will need to use %n to figure out how many bytes where consumed; it is unclear if your program should consume invalid input).

If input must be strictly validated with scanf() then you you have to read a character at a time with either %c or %1[. They preserve white and can report incomplete input:

#include <stdio.h>

#define MAX_CHAR_LENGTH 5

int main() {
    printf("enter hex values: " ); 
    char s[3*MAX_CHAR_LENGTH+1] = {0};
    for(int i = 0; i < MAX_CHAR_LENGTH; i++) {
        int rv = scanf("%1[0-9a-fA-F]%1[0-9a-fA-F]%1[ n]", s+3*i, s+3*i+1, s+3*i+2);
        if(!i && !rv) { // "n"
            int rv2 = scanf("%1[n]", s);
            if(!rv2) goto fail;
            break; 
        }
        if(rv != 3) goto fail;
        if(s[3*i+2] == 'n') break;
    }
    printf(""%s"n", s);
    return 0;
fail:
    printf("invalid input "%s"n", s);
    return 1;
}

And example runs:

enter hex values: 
"
"

enter hex values:  // <space> <enter>
invalid input ""

enter hex values: zz 
invalid input ""

enter hex values: aa // aa <space> <enter>
invalid input "aa "

enter hex values: aa
"aa
"

enter hex values: aa aa aa aa aa aa
"aa aa aa aa aa "

A better approach is separate I/O and parsing. Use fgets() or getline() to read a line. Then parse upto those 5 hex digits then print the the valid digits xor tell user about any and all errors found.

8

You can read individual characters with %c or %[ but be aware that both the terminal line discipline and the stdin buffering scheme will prevent any input from reaching the program until a newline is entered when the user hits the Enter key.

Here is a modified version:

#include <stdio.h>

#define MAX_CHAR_LENGTH 5

int main(void) {
    unsigned int curr_hex;
    char c;
    
    printf("enter hex values: " ); // prompt user to enter hex values
    
    for (int i = 0; i < MAX_CHAR_LENGTH; i++) { 
        if (scanf("%x%c", &curr_hex, &c) != 2) {
            printf("invalid inputn");
            return 1;
        }
        printf("Read hex: 0x%02Xn", curr_hex);
        if (c == 'n')
            break;
        if (c != ' ') {
            printf("invalid separator: %cn", c);
            return 1;
        }
    }
    return 0;
}

The above program will accept hex values with more than 2 digits, including values above 255. You can avoid this with this alternate approach:

#include <stdio.h>

#define MAX_CHAR_LENGTH 5

int main(void) {
    unsigned int curr_hex;
    char sep[2];
    
    printf("enter hex values: " ); // prompt user to enter hex values
    
    for (int i = 0; i < MAX_CHAR_LENGTH; i++) { 
        // read at most 2 hex digits followed by either a space or a newline
        if (scanf("%2x%1[ n]", &curr_hex, sep) != 2) {
            printf("invalid inputn");
            return 1;
        }
        printf("Read hex: 0x%02Xn", curr_hex);
        if (*sep == 'n')
            break;
    }
    return 0;
}

The above program will still accept hex values with a single digit. To ensure exactly 2 digits were entered, you can use %n to get the number of characters read and check the length:

#include <stdio.h>

#define MAX_CHAR_LENGTH 5

int main(void) {
    unsigned int curr_hex;
    int n;
    char sep[2];
    
    printf("enter hex values: " ); // prompt user to enter hex values
    
    for (int i = 0; i < MAX_CHAR_LENGTH; i++) { 
        // read at most 2 hex digits followed by either a space or a newline
        if (scanf("%2x%n%1[ n]", &curr_hex, &n, sep) != 2 || n != 2) {
            printf("invalid inputn");
            return 1;
        }
        printf("Read hex: 0x%02Xn", curr_hex);
        if (*sep == 'n')
            break;
    }
    return 0;
}

The problem with scanf is error recovery: it is cumbersome to handle invalid input gracefully. A better solution is to read input one line at a time with fgets() and parse it with sscanf or other functions.

2

Err… reading a line oriented input with scanf is masochism (or sadism from your teacher if this is an assignment). The blessed way would be to first read the line with fgets and then scan it with strtol.

Something like:

char line[32];
if (NULL == fgets(line, sizeof(line), stdin)) {       // read a full line
    ...                                 // handle the read error
}
if (strlen(line) == sizeof(line) -1) {  // a too long line?
    ...                                 // handle the error condition
}
char *start = line;                     // search for a number starting at start
char *end;                              // define an end pointer
for (;;) {
    int val = strtol(start, &end, 16);  // read an hexa value
    if (end == start) {                 // nothing more to read?
        break;                          // exit the loop
    }
    printf("Read hex: 0x%02Xn", val);
    start = end;                        // continue past the got value
}
printf("n");

If you are required to use scanf, you will have to control whether the character following the hexa value is a 'n'.

Something like:

for(;;) {
    int val;
    char c;
    if (1 != scanf("%x", &val)) {             // try to read an hex value
        ...                                   // handle the read error
        break;
    }
    if (1 != scanf("%c", &c)) {
        ...                                   // handle the read error
        break;
    }
    if (c == 'n') break;                     // got the newline!
    printf("Read hex: 0x%02Xn", val);
}

Yet this is not immune to blank characters before the end of line, so this is a very fragile code.

The robust way would be to use fgetc and ungetc:

for(;;) {
    int val;
    int c;
    if (1 != scanf("%x", &val)) {             // try to read an hex value
        ...                                   // handle the read error
        break;
    }
    do {
        c = fgetc(stdin);                     // BEWARE: getc returns an int!
        if (c == EOF) {                       // because EOF is an int constant
            ...                               // handle the read error
            break;
    } while (isblank(c));                     // will skip any space or tab
    if ((c == 'n') || (c == EOF) break;      // got the newline or an error
    ungetc(c, stdin);                         // else put c back into the stream
    printf("Read hex: 0x%02Xn", val);
}
printf("n");

But beware: none of the above code has been tested: typos can be expected…

0

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật