Showing output in a certain way - c

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 like1:
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.
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.
Once the buffer array is full, we move down a line, loop through the array, and print out the ASCII values with formatting:
Since chars are essentially ints 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.
We finally reset the buffer, and print the blank new line seen after NEW_TERMINAL_LINE characters for clarity.
The buffer is filled and reset until we have printed all of the characters in the file (the previous steps are repeated).
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).

You can first use a buffer to record the input in a line, then you can show the ASCII values of the input by transferring the characters in the buffer to integers in the following line.

Related

Counting the number of appearances of each character

I am new to C and working on homework. I got most work done, but I can't pass all test cases that used by my professor. He refuses to post cases being used in the auto grader.
What would be the cases that I have missed?
Any clue will be appreciated!!!
Write a program to remove all the blank characters (space and tab) in a line.
Then, count the number of appearances of each character.
Input
A single line with a maximum length of 5000 characters
Output
First line: The line after removing all the blank characters.
If the line is empty, don’t print anything in the output.
Next lines: Each line contains a character that appears in the line and its count.
Note that, the characters must appear according to their ASCII number order. (http://www.asciitable.com)
#include <stdio.h>
int main (){
int c = 0;
int characters[128] = {0}; // subscripts for the ASCII table
int count = 0; // number of characters been reading in
while(count < 5001 && (c = getchar()) != EOF) {
// 9 -> TAB on ASCII, 32 -> Space on ASCII
if (c != 9 && c != 32) {
putchar(c);
characters[c]++;
count++;
}
}
fflush(stdout);
printf("\n");
for (int i = 0; i < 128; i++) {
if (characters[i] != 0) {
printf("%c %d\n", i, characters[i]);
}
}
return 0;
}
Again, any help will be really appreciated!
Update:
The code has been corrected.
Probably you don't want to write
characters[index] = 0;
What you want instead is probably
text[index] = 0;

Cant scanf '-' or '+' in char array

I am doing homework to school. Task is to make program in C that can do some simple things with matrixes like *, -, +.
My program is reading matrixes and save them to int array. When the matrix input ended, I scanf to char to know what operation iam going to do with the matrixes. Operation are stores in char array. (on input can be up to 100 matrixes so 99 operations in between). If user writes * everything is okay, BUT when user writes '-' or '+' it stores '/n'. I was googling and debuging but still dont know why this happens. Any suggustions are welcome.
User input looks like this: First line is size of matrix.
2 3
76 98 -31
30 30 32
-
2 3
89 25 38
1 -32 -38
int* readMatrix(int width, int height, char arrayOperation[], int numberOfMatrix, int*err)
{
int sizeOfMatrix = ((height*width) + 3), i = 0;
char operation = 'n';
int *arrayMatrix = malloc(sizeOfMatrix* sizeof(int));
arrayMatrix[0] = width;
arrayMatrix[1] = height;
for (i = 2; i <= sizeOfMatrix; i++)
{
if (i == sizeOfMatrix)
{
if (scanf_s("%c", &operation) != EOF)
{
if (operation == '*' || operation == '-' || operation == '+')
{
arrayOperation[numberOfMatrix] = operation;
}
else
{
*err = 100;
}
}
else
{
arrayOperation[numberOfMatrix] = 'n';
break;
}
}
else if (scanf_s("%d", &(arrayMatrix[i])) == 1)
{
*err = 0;
}
}
return arrayMatrix;
}
In case of * the var operation==*,but in -,+ operation==/n. I call this function in loop, output array is stored in array of int**.
scanf("%c" reads the very next character without skipping any whitespace, so it will store whatever is after the last thing read -- usually a newline. If you want to skip whitespace, add a space to the format:
scanf(" %c", &operation)
this will skip any whitespace and store the next non-whitespace character.
You don't need this with %d as all of the conversion patterns except %c and %[ skip whitespace.
I was discusing this particular problem with my lecturer.
I understand this: when scanf reading the number it jumps over whitespace and /n.
So reading "32/n - " results in reading everything. When reading "32/n * " it stops at "*" because its not sign of any number. So its behave little stupid.
This can solve using fgets() function and read it by char.

Reading unsigned char from .txt file using fread give different values

I have the following code snipped to read 16 unsigned char values from a .txt file.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i, j, k, load_size;
unsigned char *buf;
load_size = 16;
buf = (unsigned char *)malloc(load_size);
FILE *fin;
fin = fopen("demo_input1.txt", "r");
fread(buf, 1, load_size, fin);
for(i=0;i<16;i++){
printf("%d ", *buf);
buf++;
}
system("PAUSE");
}
The file 'demo_input1.txt' contains the values 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. But I am getting output in the console values 49 32 50 32 51 32 52 32 53 32 54 32 55 32 56 32. Can anybody help me by telling me what is going wrong here? Thanks
fread is for reading raw inputs. As your file is formatted text, use the following:
int nums[SIZE];
int count = 0;
while( fscanf(fin, "%d", nums + count) == 1 ) {
if(++count == SIZE) break; /* More than expected numbers in file */
}
Later you can print using:
for(i = 0; i < count; i++) {
printf("%d ", nums[i]);
}
fscanf is one way to read formatted input from files. You can use malloc, walking pointers as shown in your original code snippet or as per your requirements.
What is going on is completly correct, yet not what you expected. So, whats going on? You read 1 byte from the file, into a char, then you output it using %d, which will output as decimal. Have a look at an ascii table, if you read the char 1, its ASCII value is 49, 32 is space, 50 is 2, and so on. You cannot just read plain numbers like that, your code, replacing the %d with %c would only work on binary files, but not on human readable files.
What you want to use instead of fread is fscanf, which works like scanf but reads from a file. There you can specify to read an integer, thus getting the whole numbers without the spaces. These you can check if they are smaller than 256, if yes, cast to char.
The other way of how this can be done is using fgets() to read the whole line to the buffer break the line using space as delimiter and later convert string to integers and store them or print them.
char buf[300];
int a[30],i=0;
while(fgets(buf,sizeof(buf),fin))
{
char *p = strtok(buf," ");
i = 0;
while( p != NULL)
{
a[i] = atoi(p);
printf("%d ",a[i]);
i++;
p = strtok(NULL," ");
}
}
PS: When fgets() is used you need to have predefined large array to hold your input else it may lead to erroneous results.
It is considering the ascii value of space as 32(ASCII for space).
Just make one simple change in the for loop.
Instead of %d use %c
for(i=0;i<16;i++)
{
printf("%c ", *buf);
buf++;
}

Read number from a file and replace it with another number

12 23 34 45 56
34 23 56 21 43
12 57 98 34 12
The above is the content of a txt file.
With C, i can use fgetc(myFile) to get the first integer and store into an integer variable.
I will check whether it is 12.
if it is 12, i want to replace with 25. How do i exactly replace it a certain number.
How do i rewrite a certain part of it?
Or do i store every number into an array, replace all 12s with another numbers and overwrite the whole file??
Save result to another file, than renames it. This code opens homework.txt, replaces all 12 -> 25 and writes result to homework_new.txt
#include <stdio.h>
#include <string.h>
#define MAXBUF 42
#define HOMEWORKFILE "homework.txt"
#define HOMEWORKNEWFILE "homework_new.txt"
int main(int argc, char **argv)
{
char buf[MAXBUF+1];
char str[MAXBUF+1];
FILE *hw;
FILE *hw_new;
int length;
int i, j;
int number;
char is_first;
int n_line = 0;
hw = fopen(HOMEWORKFILE, "r");
hw_new = fopen(HOMEWORKNEWFILE, "w");
if (!hw)
{
fprintf(stderr, "File not found: %s\n", HOMEWORKFILE);
return 5;
}
while(!feof(hw))
if (fgets(buf, MAXBUF, hw) != NULL)
{
length = strlen(buf);
j = 0;
str[0] = 0;
is_first = 1;
n_line++;
/* parse string */
for(i = 0; i < strlen(buf); ++i)
{
if (isblank(buf[i]) || buf[i] == '\0' || buf[i] == '\n')
{
str[j] = 0;
number = atoi(str);
if (is_first)
is_first = 0;
else
fprintf(hw_new, " ");
if (number == 12)
fprintf(hw_new, "%d", 25);
else
fprintf(hw_new, "%d", number);
j = 0;
}
else if (isdigit(buf[i]))
{
str[j++] = buf[i];
}
else
{
fprintf(stderr, "bad input on line %d '%s'\n", n_line, buf);
return 100;
}
}
fprintf(hw_new, "\n");
}
fclose(hw_new);
fclose(hw);
return 0;
}
If it's a small file , to overwrite the whole file is a good idea and easier.
If it's not limited in c language, you can try powerful tools like "sed" or some script language.
Here's a list:
fgets
ftell
fseek
fputs
Note that you need to ensure the correct lengths of the data written, in order to overwrite exactly what you want.
Another option would be, as you said, to overwrite the whole file, then you also need
freopen

reading unknown number of integers from stdin (C)

I need to read an input file like :
1
19 20 41 23
2
41 52 43
3
90 91 941
4
512
5
6
51 61
Each odd line is an integer. Each even line is unknown number of integers.
It is very easy in C++
while( cin >> k ){
............
}
I'm not so used to C, so I couldnt make it in C. Any ways to do it?
Running your input file through:
#include <stdio.h>
int main() {
int k;
while (scanf("%d", &k) == 1) {
printf("read number: %d\n", k);
}
return 0;
}
Results in:
read number: 1
read number: 19
read number: 20
read number: 41
read number: 23
read number: 2
read number: 41
read number: 52
read number: 43
read number: 3
read number: 90
read number: 91
read number: 941
read number: 4
read number: 512
read number: 5
read number: 6
read number: 51
read number: 61
This is the C analog of the code you reference in your original question.
The way I would do it is to break it down into two operations: read a line, then read the integers in that line. Here is a lazy implementation using the standard C library:
char line[1024], *p, *e;
long v;
while (fgets(line, sizeof(line), stdin)) {
p = line;
for (p = line; ; p = e) {
v = strtol(p, &e, 10);
if (p == e)
break;
// process v here
}
}
I would break the program in different tasks.
The first step is to be able to read a pair of lines, the first line which tells you the number of numbers to read, and then the second line to read the actual numbers. For this, a function called something like read_set might be useful. It should be able to return the numbers read, and signal end of file as well as errors. For this, we can define a data structure such as:
struct numbers {
long *data; /* or choose a type depending upon your needs */
size_t len;
};
and then we can declare our function with the prototype:
int read_set(FILE *fp, struct numbers *num);
The function will allocate memory for num->data, and set num->len to the correct value. It returns 0 for success, and a set of error conditions otherwise. We might get fancy and use an enum for return statuses later. For now, let's say that 0 = success, 1 = end of file, and everything else is an error.
The caller then calls read_set() in a loop:
struct numbers numbers;
int status;
while ((status = read_set(fp, &numbers)) == 0) {
/* process numbers->data, and then free it */
}
if (status == 1) {
/* hit end of file, everything is OK */
} else {
/* handle error */
}
For implementing read_set(): it has to read two lines. There are many implementations of reading a full line in C, so you can use any of them, and read a line first, then sscanf()/strtoul() it for one number (check its return value!). Once you have the number of numbers, n, you can read the next line in memory, and do:
num->data = malloc(n * sizeof *num->data);
num->len = n;
You can then repeatedly call sscanf() or strtol() to store numbers in num->data. You should put in checks to make sure exactly n numbers are on that line.
Note that you can write read_set() in other ways too: read a line character by character, and parse the numbers as you read them. This has the advantage of going over the data only once, and not needing a big buffer to store the whole input line in memory, but the disadvantage is doing low-level stuff yourself and reading data character-by-character may be slow.
I would do one of:
fgetc() to read individual characters and parse them yourself (accumulate digits until you hit whitespace and you have an integer to convert with atoi(); if the whitespace is a newline, then it terminates a list of integers)
fgets() to read a line at a time, and then parse the string (again, look for whitespace separating the values) that it returns.
I came up with a solution like this:
#include <stdio.h>
int main(void)
{
int index = 0;
char ch;
int arr[1024];
while(scanf("%d%c", &arr[index++], &ch)!=EOF)
{
if(ch=='\n')
{
// One line is read into arr
// number of integers in this line = index
// Rest of your code which can proces arr[]
// Example
int i;
for(i = 0; i < index; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
// Set the index back to 0 for the upcoming line
index = 0;
}
}
return 0;
}
have a look at getc(3) or scanf(3)

Resources