Does fgets store a newline or just \0? - c

I am confused. Over the internet you can see different answer, so what is the real answer? Thanks.
What will be stored in name?
Assume the user types the following:
JennyENTER
20ENTER
void function()
{
int product;
char name[10];
fgets(name, 10, stdin);
scanf("%d", &product);
}
A. Jenny\0
B. Jenny\n\0

When the input is short enough to fit, the newline will be included.
If the data before the newline is 9 characters or more (for the code above), the newline will not be included and the extra characters and newline will be left in the input stream to be read by another input call. If you enter Jenny (and a newline), the newline will be included. If you enter Jennifer, you also get the newline, but if you enter Stephanie and a newline, you don't get the newline (it's left behind to be read by another input function). If you enter Antidisestablishmentarianism, you get the input string Antidises\0, and tablishmentarianism is left for other input code to read.

Check out this small program.
When running, give inputs with length greater than 10 and less than 10.
You see that a new line (10)dec will be stored before storing \0 if input length is less than 10.
#include <stdio.h>
int main()
{
char str[10] = {0};
int i = 0;
fgets(str,sizeof(str),stdin);
while(str[i])
{
printf("%d %d = %c\n" ,i, str[i], str[i]);
i++;
}
printf("%d %d = %c\n" , i, str[i], str[i]);
return 0;
}
ABCDEFGHIJKLM
0 65 = A
1 66 = B
2 67 = C
3 68 = D
4 69 = E
5 70 = F
6 71 = G
7 72 = H
8 73 = I
9 0 =
HELLO
0 72 = H
1 69 = E
2 76 = L
3 76 = L
4 79 = O
5 10 =
6 0 =

Related

Storing and Iterating through user inputs in C

The program below asks the user to input 10 integer numbers and stores the user inputs in a corresponding array of 10 ints. When an input is done it should iterate through the already existing user inputs and print them out. I want to iterate through the stored values in storedinputs by using a function like strlen(), however the stored values are not strings but are integers. How could i do such a thing.
int main(void) {
int storedinputs[10] = {0};
int input;
for(int i = 0; i < 10; i++) {
printf("\nPlayer input:");
scanf("%d", &input);
storedinputs[i] = input;
for(int s = 0; s < strlen(storedinputs); s++) {
printf("Inputs %d", storedinputs);
}
}
return 0;
}
Expected Output:
Player input: 1
Inputs: 1
Player input: 3
Inputs: 1 3
Player input: 60
Inputs: 1 3 60
You cannot use the function strlen() because storedinputs is an array of integers. If you want to print the stored values every time you insert a new one you should edit the for loop condition, as suggested by Weather Vane in the comments, as follows:
for(int s = 0; s <= i; s++)
The variable i indicates the number of the cell containing the last number added.
Here is the fixed code including error checking.
Superfluous input needs to be skipped over (while(fgetc(stdin) != '\n');)
scanf has insufficient error checking capabilities. Use combination of fgets and strtol.
In the internal loop you need to terminate when outer loop counter is reached
You should not count invalid input (Therefore, I replaced outer for loop by a while loop)
You should not store invalid inputs in your array
You need to index your stored inputs when printing them out
--
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
// In contrast to #define this provides a nice means for grouping constants
// and it can be changed into a typedef, later on
// Furthermore, it's a compiler aware constant
enum {INPUT_COUNT = 10, MAX_INPUT_LENGTH = 20};
int main(void) {
int input_count = 0; // The count of valid inputs
char input[MAX_INPUT_LENGTH + 1] = {0}; // The string buf for one input
int converted_input; // Result of integer conversion
int storedinputs[INPUT_COUNT] = {0}; // Array with valid results
char *endptr; // Needed for strtol error checking
while(input_count < 10) { // Loop over 10 valid inputs
printf("\nPlayer input (Enter single integer value):");
fgets(input, sizeof(input), stdin);
printf("Got input: %s\n", input); // input contains '\n', already
// If input was longer than MAX_INPUT_LENGTH, get rid of remains
if (input[strlen(input) - 1] != '\n') {
while(fgetc(stdin) != '\n');
}
// Reset errno, so strtol returns a fresh value
errno = 0;
converted_input = strtol(input, &endptr, 10);
// The errno is set if input is out of range
if (errno) {
perror("Conversion error");
continue;
}
// Here we have invalid characters present in the input
if ( (endptr == input) || (*endptr != '\n') ) {
printf("Please enter single integer!\n");
continue;
}
// Everything fine, so we can store result
storedinputs[input_count] = converted_input;
// Now we output all valid inputs, up to now
printf("Inputs: ");
for(int s = 0; s <= input_count; s++) {
printf("%d ", storedinputs[s]);
}
printf("\n");
++input_count;
}
return 0;
}
Output:
Player input (Enter single integer value):12
Got input: 12
Inputs: 12
Player input (Enter single integer value):13
Got input: 13
Inputs: 12 13
Player input (Enter single integer value):14
Got input: 14
Inputs: 12 13 14
Player input (Enter single integer value):1324567543245678654324567
Got input: 13245675432456786543
Conversion error: Numerical result out of range
Player input (Enter single integer value):asdc
Got input: asdc
Please enter single integer!
Player input (Enter single integer value):
Got input:
Please enter single integer!
Player input (Enter single integer value):12 12 12
Got input: 12 12 12
Please enter single integer!
Player input (Enter single integer value):1
Got input: 1
Inputs: 12 13 14 1
Player input (Enter single integer value):2
Got input: 2
Inputs: 12 13 14 1 2
Player input (Enter single integer value):3
Got input: 3
Inputs: 12 13 14 1 2 3
Player input (Enter single integer value):4
Got input: 4
Inputs: 12 13 14 1 2 3 4
Player input (Enter single integer value):5
Got input: 5
Inputs: 12 13 14 1 2 3 4 5
Player input (Enter single integer value):67
Got input: 67
Inputs: 12 13 14 1 2 3 4 5 67
Player input (Enter single integer value):7
Got input: 7
Inputs: 12 13 14 1 2 3 4 5 67 7
OK, 10 inputs have been made

How to use input letter to print on the screen the list of employees whose name starts with that letter and their corresponding info

The problem consist of 2 array structures and each task is broken down into functions. I need help with the function that would ask the user for a letter and print on the screen the list of employees whose name starts with that letter.
These are the files.
employees.txt
Jimmy OBrien 1234567D Irish 40 1 2
David Keogh 3234567F Irish 61 0 0
David Hanahoe 5234567G Irish 48 1 2
Tom Byrne 6234567N Irish 62 1 4
Thomas Collins 8234567B Irish 35 0 0
Aoife Murphy 4234567F Irish 63 1 3
Joan OBrien 5234567M Irish 36 1 1
Maria Ionescu 7734567E Romanian 43 1 2
Celine Keogh 2254893R Irish 38 1 0
benefits.txt
1234567D 37500 20 10 0
3234567F 40000 20 10 0
5234567G 42000 20 10 0
6234567N 45000 20 10 0
8234567B 47000 20 10 0
4234567F 50000 20 10 0
5234567M 55000 20 10 0
7734567E 60000 20 10 0
5234997P 75000 20 10 0
2254893R 75000 20 10 0
void input_letter()
{
char letter[1];
int i;
printf("Please enter a letter of a employee. \n ");
scanf("%c", letter);
printf("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE\n");
for(i = 0; i < no_emplo; ++i)
{
if(strcmp(emplo[i].name, letter) == 0) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance);
}
}
}
When I run this code, it only prints out the first 2 print functions and doesn't even allow me to input a letter.
You said you wanted to read one letter from stdin. But your variable letter is an array of size 1. It is not long enough to store a string of length 1 and the terminating '\0', so it can't be used with the %c format specifier.
Why don't you simply use a char?
void input_letter(void)
{
puts("Please enter a letter of a employee.");
char letter;
if (scanf(" %c", &letter) != 1) {
fputs("Input error!\n\n", stderr);
return;
}
puts("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE");
for(size_t i = 0; i < no_emplo; ++i)
{
if(emplo[i].name[0] == letter) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance
);
}
}
}
Please consider these changes:
void input_letter()
{
char letter;
int i;
printf("Please enter a letter of a employee. \n ");
scanf("%c", & letter);
printf("\nNAME\tSURNAME\tPPS\tSALARY\tPENSION\tALLOWANCE\n");
//Prints the table
for(i=0; i<no_emplo; i++)
{
if(emplo[i].name[0] == letter) {
printf("\n%s\t%s\t%s\t%d\t%d\t%d\n",
emplo[i].name,
emplo[i].surname,
emplo[i].PPS,
bene[i].salary,
bene[i].pension,
bene[i].allowance);
}
}
}

Input ints separated by whitespace and pass them to an int array

I'm trying to write a program in C where the user inputs a defined number of ints (in this case 5 ints) separated by whitespaces. Then, the input is stored in an int array so, lastly, it can be stored in a char array.
As an example of how the program is intended to work, when it asks for an input:
Input: 20 5 63 4 127
The output of the program should be:
Output: 20 5 63 4 127
This is what I've written so far, but I don't know how to get the input transformed into an int array. Note that I know the length of the input beforehand (in this case, as said above, 5 ints).
// Input: 20 5 63 4 127
// Ask for user input.
// Store the input in this int array.
int input_int_array[5];
unsigned char char_array[5];
for(int i=0;i<5;i++)
{
char_array[i]=input_int_array[i];
printf("%d ", char_array[i]);
}
// Should print: 20 5 63 4 127
You are probably expected to use scanf() to read user input as integers into an array of int:
#include <stdio.h>
int main() {
int input_int_array[5];
// Ask for user input.
printf("input 5 numbers: ");
for (int i = 0; i < 5; i++) {
// Store the input into the array.
if (scanf("%d", &input_int_array[i]) != 1)
return 1;
}
// Output the contents of the array:
for (int i = 0; i < 5; i++) {
printf("%d ", input_int_array[i]);
}
printf("\n");
return 0;
}

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 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.

i'm not processing more than one block correctly

I have an assignment where I'm suppose to read input lines such as
2
67 5 100 1 11 97 98 10 1 110
15 72 10 101 47 67 88 20 94 6 22 11
4
61 11 93 4 73 39 78 34 17 104
23 43 11 93 65 52 20 96 66 31 86 24 40 61 102 13 50 51
73 43 28 73 8 89 31 68 77 27 24 77 42 72 15 24 64 51
25 75 7 90 10 111 17 16
.....
process every two integers (the first line in a block only tells us how many words we will process), add them then match
them to their corresponding ASCII char. The example above would be two blocks.
The output should be:
Decoded messages:
Hello World!
Happy Bhutanese teacher's day!
I'm having problems when it comes to dealing with a file with multiple blocks, more than 20 and so forth following the same format on one input text. I can handle one block fine, two blocks okay but not fine because my program doesn't seem to end. No line will be longer than 256 characters. numOfPuzzl refers to how many words we process per block.
I'd greatly appreciate any help. I attached my code and commented as much as I can too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
//user will type in file name they choose to process and we allocated in filename[]
char filename[256];
printf("Enter filename: ");
scanf("%s", filename);
//process filename username typed in
FILE *pFile;
pFile = fopen(filename, "r");
//if there's nothong to read
if (pFile == NULL){
exit(1);
}
printf("Decoded messages:\n");
//create array we will putting lines into
char myString[256];
//simply gets the first line, which is always a lone integer
fgets(myString, 256, pFile);
int numOfPuzzl;
sscanf(myString, "%d", &numOfPuzzl);
//printf("puzzles to solve: %d\n", numOfPuzzl);
int wordsProcessed = 0;
//just remember that myString has entire line
//start processing the lines that follow, a line is a word
while (fgets(myString, 256, pFile) != NULL){
int num = 0; //first integer in line
int secondNum = 0; //second int. in line
int tot = 0; //how many bytes
int bytes_read = 0; //bytes processed
char *endOfStrAdr = strchr(myString, '\0'); //returns address of end terminating char.
int endOfStrIdx = endOfStrAdr - myString; //this will give me the index of where the terminating char. occurs within my array
//start scanning integers within array making sure to not sccan out of bounds
while (tot < endOfStrIdx){
//first integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &num, &bytes_read);
tot += bytes_read; //keeps tab so we don't have to read from the begn. of array everytime
//second integer allocated as well as how many byes it was
sscanf(myString + tot, "%d %n", &secondNum, &bytes_read);
tot += bytes_read; ////keeps tab so we don't have to read from the begn. of array everytime
printf("%c", (char) num + secondNum); //add the two integers and cast them to char
//we want to check if we are the end of the string, our word
if (tot == endOfStrIdx){
printf(" ");
wordsProcessed++;
//we want to print a new line char. if we finished processing all the words for the puzzle
if (wordsProcessed == numOfPuzzl){
printf("\n");
fgets(myString, 256, pFile);
}
}
}
}
fclose(pFile);
}
Ignore blank lines between puzzles.
Reset parameters (numOfPuzzl and wordsProcessed) before processing new puzzles.
To archive that, change
if (wordsProcessed == numOfPuzzl) {
printf("\n");
fgets(myString, 256, pFile);
}
into
if (wordsProcessed == numOfPuzzl) {
printf("\n");
while ( fgets(myString, 256, pFile) != NULL ){
if ( sscanf(myString, "%d", &numOfPuzzl) == 1 )
break;
}
wordsProcessed = 0;
}
I suggest like this:
#include <stdio.h>
#include <stdlib.h>
//stringize macro
#define S_(x) #x
#define S(x) S_(x)
int main(void){
char filename[FILENAME_MAX + 1];
printf("Enter filename: ");
scanf("%" S(FILENAME_MAX) "[^\n]", filename);
FILE *pFile;
if(NULL==(pFile = fopen(filename, "r"))){
perror("can't opne file");
exit(EXIT_FAILURE);
}
printf("Decoded messages:\n");
int numOfLines;
while(1==fscanf(pFile, "%d", &numOfLines)){
for(int i = 0; i < numOfLines; ++i){
int num1, num2, state;
char ck;
while(3==(state=fscanf(pFile, "%d %d%c", &num1, &num2, &ck)) || 2 == state){
putchar(num1 + num2);
if(state == 2 || state == 3 && ck == '\n')
break;
}
putchar(' ');
}
putchar('\n');
}
fclose(pFile);
return 0;
}

Resources