简体   繁体   中英

Showing output in a certain way

I am trying to print out the ASCII values of all the characters in a text file.

int main(int argc, char* argv[]) {
        FILE *fp;
        int c;
        fp = fopen(argv[1], "r");
        while((c = fgetc(fp)) != EOF) {
                printf("%c %3d\n", c, (int)c);
        }
        fclose(fp);
        return 0;
}

Is it possible to show the output as shown below?

r     a     n     d     o     m
114   97   110   100   111   109

Assuming the first word in my input file is 'random'. Thanks

Yes, as hexiecs said, it is very possible. Asking how would be a much better question. I am going to assume this is what you mean.

Here is an example of how you might go about doing this:

#include <stdio.h>
#define NEW_TERMINAL_LINE 10

void print_current_characters(char char_equivalents[]);

int main(int argc, char const *argv[]) {
  char char_equivalents[NEW_TERMINAL_LINE] = {0};

  int c;
  int i = 0;
  int final_position; /* Store the final position that we will use later
                       * to get the remaining characters in the buffer */

  FILE *file;
  file = fopen("file.txt", "r");
  if (file) {
    while ((c = getc(file)) != EOF) {
        if (i > NEW_TERMINAL_LINE - 1) {
          /* Every time the buffer fills up, we need to go to a new line
           * in the output as well (defined by NEW_TERMINAL_LINE).
           * Then we need to clear the buffer and make a new line 
           * to start off printing again!
          */
          print_current_characters(char_equivalents);
          int j;
          for (j = 0; j < sizeof(char_equivalents)/sizeof(char_equivalents[0]); j++) {
            char_equivalents[j] = 0; /* Clear the filled up buffer */
            i = 0;
          }
          printf("\n\n");
        }
        /* Print the character itself (we will print the ASCII when the buffer fills up) */
        char_equivalents[i] = c;
        if(char_equivalents[i] == '\n') {
          printf("\\n\t");
        } else if (char_equivalents[i] == '\t') {
          printf("\\t\t");
        } else if (char_equivalents[i] == ' ') {
          printf("[space]\t");
        } else {
          printf("%c\t", c);
        }
        final_position = i;
        i++;
    }

    /* Print any remaining characters in the buffer */
    print_current_characters(char_equivalents);

    fclose(file);
  }
  printf("\n");
  return 0;
}
void print_current_characters(char char_equivalents[]) {
  printf("\n");
  int i;

  for(i = 0; i < NEW_TERMINAL_LINE; i++) {
    if (char_equivalents[i] == 0 || NULL) {
      break; /* Don't print if there is nothing but 0s in the buffer */
    }
    if(char_equivalents[i] == '\n') {
      printf("\\n\t\t");
    } else if (char_equivalents[i] == '\t') {
      printf("\\t\t");
    } else {
      printf("%d\t", (int)char_equivalents[i]); /* Print the ASCII character */
    }
  }
}

With my previous edit, Jonathan Leffler and I were discussing what would happen if the buffer filled up since the original poster said in a comment:

I am assuming the input file will have a maximum 1000 characters.

The output would be a very long line unless there were newlines after a certain amount of characters.

We could just have an array with a maximum buffer of 1000, but we could also save more memory by just processing the file every x amount of characters. Here, after every NEW_TERMINAL_LINE number of characters, we can create a new line and print out the current buffer. Finally we can empty the buffer, and continue processing the characters. In fact, using this approach, the buffer is only limited by the available memory on the computer .

Say we want the maximum number of characters (and the corresponding ASCII values) on a line to be displayed as 10. The text file contains the string: random random random random random random random random [enter] (Hypothetically, the string could be much longer and the program would still display it neatly). The output of this program looks like 1 :

r   a   n   d   o   m   [space] r   a   n   
114 97  110 100 111 109 32     114  97  110 

d   o   m   [space] r   a   n   d   o   m   
100 111 109 32     114  97  110 100 111 109 

[space] r   a   n   d   o   m   [space] r   a   
32     114  97  110 100 111 109 32     114  97  

n   d   o   m   [space] r   a   n   d   o   
110 100 111 109 32     114  97  110 100 111 

m   [space] r   a   n   d   o   m   [space] r   
109 32     114  97  110 100 111 109 32     114  

a   n   d   o   m   \n  
97  110 100 111 109 \n

if NEW_TERMINAL_LINE is set to 10 .

  1. We end up storing the ASCII equivalents in an array named char_equivalents . For every character we come across, we store it in the array, and then we print it out followed by a tab.

  2. Once the buffer array is full, we move down a line, loop through the array, and print out the ASCII values with formatting:

    Since char s are essentially int s in disguise as ASCII, we simply typecast the char as an int . This will print out the corresponding ASCII value. Afterwards, we add a tab to make sure everything aligned with the line above. With this information, it is not difficult to loop through the array and print out the corresponding information.

  3. We finally reset the buffer, and print the blank new line seen after NEW_TERMINAL_LINE characters for clarity.

  4. The buffer is filled and reset until we have printed all of the characters in the file (the previous steps are repeated).

  5. In the end, sometimes the buffer isn't full so we never printed out the remaining ASCII equivalents for the last line in the output. We simply call print_current_characters() again.


1 I don't really think this was the best way to format the code, but at the same time, I did want to honor the format that the original post asked for.

It will become more convenient if you process individual words instead of each characters. This way you can print each individual characters of the words first, and then print ASCII values of each characters the words next.

You can do try something like this.

int main(int argc, char* argv[]) {
    FILE *fp;
    int c;
    char line[100];  /* Buffer to hold each line */
    fp = fopen(argv[1], "r");
    /* get each line, and print each word of the line */
    while (fgets(line, 100, fp) != NULL) {
            line[strlen(line) - 1] = '\0';
            print_words(line);
    }
    fclose(fp);
    return 0;
}

/* print_words: print each word from line */
void print_words(char *line)
{
    char *word;

    /* get each word, and print them with ascii values */
    if ((word = strtok(line, " ")) != NULL)
            ascii_print(word);
    while ((word = strtok(NULL, " ")) != NULL)
            ascii_print(word);
}

/* ascii_print: print each char and its ascii values for a word*/
void ascii_print(char *word)
{
    int i, len;

    len = strlen(word);

    /* print the word */
    for(i = 0; i < len; i++)
            printf("%-4c", word[i]);
    printf("\n");

    /* print ascii values */
    for(i = 0; i < len; i++)
            printf("%-4d", word[i]);
    printf("\n");
}

Note that above program is not totally correct, and may produce buggy results in some test cases. However it shows the idea that it is easier if you process word by word, instead of character by character.

Although, the code is simple, you may have to see manual pages of fgets() and strtok() if you are not familiar with them.

Briefly saying, fgets() gets a line from a file, and strtok() gets each word from a line. For more info, you need to do man 3 strtok and man 3 fgets in Google (or in command line if using Unix-like machine).

您可以首先使用缓冲区在一行中记录输入,然后可以通过将缓冲区中的字符转换为下一行中的整数来显示输入的ASCII值。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM