Scanning white space with fgets() - c

I'm running user input through a series of functions provided by the ctype.h library, but scanf doesn't work for white space.
Since I can't use scanf for whitespace I believe fgets() should be what I'm looking for, but am unsure about the last parameter I would use for it. Any advice would be appreciated!
#include <stdio.h>
#include <ctype.h>
int main(void) {
char a;
puts("Enter a character:");
//scanf("%s", &a);
fgets(a, 1, ??);
printf("isblank('%c') = %d \n", a ,isblank(a));
printf("isdigit('%c') = %d \n", a ,isdigit(a));
printf("isalpha('%c') = %d \n", a ,isalpha(a));
printf("isalnum('%c') = %d \n", a ,isalnum(a));
printf("isxdigit('%c') = %d \n", a ,isxdigit(a));
printf("islower('%c') = %d \n", a ,islower(a));
printf("isupper('%c') = %d \n", a ,isupper(a));
printf("tolower('%c') = %d \n", a ,tolower(a));
printf("toupper('%c') = %d \n", a ,toupper(a));
printf("isspace('%c') = %d \n", a ,isspace(a));
printf("iscntrl('%c') = %d \n", a ,iscntrl(a));
printf("ispunct('%c') = %d \n", a ,ispunct(a));
printf("isprint('%c') = %d \n", a ,isprint(a));
printf("isgraph('%c') = %d \n", a ,isgraph(a));
return 0;
}
Output should look like this
Enter a character:
C
isblank('C') = 0
isdigit('C') = 0
isalpha('C') = 1024
isalnum('C') = 8
isxdigit('C') = 4096
islower('C') = 0
isupper('C') = 256
tolower('C') = 99
toupper('C') = 67
isspace('C') = 0
iscntrl('C') = 0
ispunct('C') = 0
isprint('C') = 16384
isgraph('C') = 32768
Program should intake a single character and convert it to integer through a series of functions.

The first argument to fgets() needs to be a buffer that can hold the entire line of input.
int main(void) {
char a;
char line[100];
puts("Enter a character:");
fgets(line, sizeof line, stdin);
a = line[0];

Related

Passing a non-digit char after an integer to scanf

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, k;
scanf("%d %d", &n, &k);
printf("%d %d\n", n, k);
return 0;
}
In the above sample code passing to the input
1 2
Would produce an expected output of
1 2
However passing any char in-between these two digits such as
1. 2 or 1 d 3
Will result in a strange output of the following
1 32766
I would like to know why this occurs, as it was to my belief that scanf would skip over any non-digit input.
You should check the return value of scanf, which tells you the number of data that are read into the passed arguments, here it is k.
In your case, the return value will be zero as %d cannot be used to read in a char in C. If the first input is a char it will be 0, 1 if the first value is int and the second value is a char, 2 if both of the values are int.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n, k, rc;
rc = scanf("%d %d", &n, &k);
if (rc != 2)
{
printf("scanf failed to set the values for n and k\n");
}
else
{
printf("valid input for n and k\n");
}
printf("%d %d\n", n, k);
return 0;
}
So the int k is uninitialized and thus it will store some random value as scanf failed to set the value for this variable.
(Too long for a comment.)   The following answers OP's followup question from a comment.
is there anyway to pass over the character that stops the input stream?
scanf may not be the best or easiest way to do that, but it's still possible to do it using the %n format specifier which returns the offset into the original string during parsing. Following is an example, which uses sscanf but can be easily adapted to scanf.
#include <stdio.h>
void read_three_ints(const char *str) {
int a, n1, b, n2, c;
int ret = sscanf(str, "%d %n%d %n%d", &a, &n1, &b, &n2, &c);
switch(ret)
{
case 3:
printf("'%s': a = %d, b = %d, c = %d\n", str, a, b, c);
break;
case 2:
printf("'%s': a = %d, b = %d, error parsing c = `%s`\n", str, a, b, str + n2);
break;
case 1:
printf("'%s': a = %d, error parsing b = `%s`\n", str, a, str + n1);
break;
case 0:
printf("'%s': error parsing a\n", str);
break;
default:
printf("'%s': scanf error %d\n", str, ret);
break;
}
}
int main()
{
read_three_ints("1 2 3");
read_three_ints("1 2 x");
read_three_ints("1, 2 ");
read_three_ints(";1 ");
read_three_ints("");
return 0;
}
Output:
'1 2 3': a = 1, b = 2, c = 3
'1 2 x': a = 1, b = 2, error parsing c = `x`
'1, 2 ': a = 1, error parsing b = `, 2 `
';1 ': error parsing a
'': scanf error -1

Print string pointer causes corrupted output in C

#include <stdio.h>
#include <stdlib.h>
struct cal {
int date;
int time;
int importance;
char title[256];
char description[256];
};
int count;
void change_Cal (struct cal *calendar) {
for (long long int i = 0; i < count; i++) {
int year = 0, month = 0, day = 0;
year = calendar[i].date / 10000;
month = (calendar[i].date - 10000 * year) / 100;
day = calendar[i].date % 100;
printf("%04d.%02d.%02d. ", year, month, day);
int hour, min;
hour = calendar[i].time / 100;
min = calendar[i].time % 100;
printf("%02d:%02d %d %s %s\n",hour,min,calendar[i].importance, calendar[i].title, calendar[i].description);
}
}
int main() {
struct cal *calendar;
//struct cal calendar[1024] = { 0, };
printf("please input the number of the calender.\n>");
scanf("%d", &count);
calendar = (struct cal *)malloc(sizeof(struct cal)*count);
calendar = (struct cal *)calloc(count, sizeof(struct cal));
printf("input calendars.\n");
for (int i = 0; i < count; i++) {
printf(">");
scanf("%d %d %d %c %c", &calendar[i].date, &calendar[i].time, &calendar[i].importance, calendar[i].title, calendar[i].description);
printf("\n");
}
change_Cal(calendar);
}
The
printf("%02d:%02d %d %s %s\n",hour,min,calendar[i].importance, calendar[i].title, calendar[i].description);
part is not working.
Some data is corrupted too.
Input : 20180927 0900 0 iiii
Output: 2018.09.27. 09:00 0 i i
Process returned 0 (0x0) execution time : 12.588 s
I think some pointers are the problem.
What's the problem?
You use this
scanf("%d %d %d %c %c", &calendar[i].date, &calendar[i].time, &calendar[i].importance, calendar[i].title, calendar[i].description);
to read this
20180927 0900 0 iiii
^ ^ ^ ^^
%d %d %d cc
So you get a number, a number, a number, a character ('i') and a character ('i').
Did you notice the risk of confusing a number with a leading 0 with an octal number?
The blank in the format string between the two expected characters, will be parsed as "take any present whitespace" which for "iiii" is "no whitespace".
You will leave in the input stream "ii\n"; which will confuse the next attempt to scan a number and make it fail. I.e. the return value of the next scan-attempt (which you ignore in your code) will be 0, while it should be 5.
To fix read about all the things that can go wrong with complex input scanning via scanf:
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
Then change to something which can read strings instead of character, but probably not scanf().

Double usage of scanf() depends on call order

I wrote a program in C which takes as an input a value and an ordered Array of integers and performs a ternary search to find the value(if it exists) inside the Array.
I have seen all the possible problems with the usage of scanf and the related topics here in Stackoverflow.
I have noticed that there is a difference if I call the 2 scanf functions in reverse order.
If I use the code as it is below. First read the value and after the array from the user, the program and scanf functions as expected.
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
Although if I use the scanf inputs in the reverse order the second scanf never stops to get user input and read values left in the buffer.
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
I cannot understand what is the difference in the calling order.
I have tried the solutions mentioned in the other threads but none worked.
Just as a reference here is the whole code(working as expected):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int ternarySearch(int A[], int l, int r, int k){
int i;
int first,second;
if(l>r){
return -1;
}
i= (r - l)/3;
if(i==0){
i++;
}
first = i+l-1;
second = i*2+l-1;
if(A[first]==k){
return first;
}
else if(A[first]>k){
ternarySearch(A, l, first-1, k);
}
else
{
if(A[second]==k)
return second;
else
if(A[second]>k)
ternarySearch(A, first+1,second-1, k);
else
ternarySearch(A, second+1,r, k);
}
}
int main(){
const int maxarraylen = 1000;
int i;
int n;
int A[maxarraylen];
char string[250];
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
n=i-1;
//We assume the array is sorted otherwise we can use any sorting algorithm e.g. code from task1
scanf(" %d", &k);
int result;
result=ternarySearch(A, 0, n, k);
if(result==-1){
printf("The value was not found in the Array.\n");
}
else{
printf("The value was found in position no. %d.\n", result);
}
return 0;
}
Your problem is that you are not 'stepping over' your end input.
We can see this by doing an experiment using the following program:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
FILE *f;
long f_pos;
int ret;
int i;
int data[5];
int data_last;
int search;
f = fopen("./input.txt", "r");
if (f == NULL) {
perror("fopen()");
return;
}
/* read in the values for the array */
data_last = -1;
for (i = 0; i < 5; i++) {
ret = fscanf(f, "%d", &(data[i]));
printf("fscanf(data[%d]): ret: %d\n", i, ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
if (ret != 1) {
break;
}
data_last = i;
}
/* check that we read in at least one value */
if (data_last == -1) {
printf("no input data!\n");
return;
}
/* insert 'fix' here */
/* pre-load the 'search' with known garbage */
search = 987;
/* now read in the search value */
ret = fscanf(f, "%d", &search);
printf("fscanf(search): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
/* print out our info */
for (i = 0; i <= data_last; i++) {
printf("data[%d]: %d\n", i, data[i]);
}
printf("search for: %d\n", search);
return;
}
With the following data in input.txt:
123
456
end
456
The output is as follows:
fscanf(data[0]): ret: 1
ftell(): 3
fscanf(data[1]): ret: 1
ftell(): 7
fscanf(data[2]): ret: 0
ftell(): 8
fscanf(search): ret: 0
ftell(): 8
data[0]: 123
data[1]: 456
search for: 987
ftell() tells us where the file's cursor is, and in this case we can see that it is at byte 8... the e of the input line end.
It doesn't get past it, and thus the next attempt to read a number (%d) will fail too!
It's also a good idea to check the return values! We can see that the fscanf(&search) call has failed to read a number!
The solution is to insert this snippet just after we check that we recieved array values:
/* this is the 'fix' */
ret = fscanf(f, "end");
printf("fscanf(end): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);

concatenating char to int type

Been racking my brain for the past few hours but i need help. Pretty much trying to write a C model for a blocking cache to be used in a RTL design. I've defined the cache line in C as an array of 'char' types to make it byte-addressable. Only difficulty is I can't for the life of me figure how to concatenate four bytes (chars) into a 32bit 'int' type to be returned. I've tried everything I could think of using strcat, strncat, strcpy, etc but no luck. strcat returns the proper value when I the char array is populated with actual characters, but it doesn't behave as desired when numbers are use (strcat only returns the first element instead of the entire char array). Example code:
unsigned char aa[4] = {0};
char testet[2] = {1,0};
printf(" aa[0] = %d \n", aa[0]);
printf(" aa[1] = %d \n", aa[1]);
printf(" aa[2] = %d \n", aa[2]);
printf(" aa[3] = %d \n", aa[3]);
printf(" aaconcat as a 32b word is %u \n", *strncat(aa, testet,2));
printf(" aaconcat as a 32b word is %u \n", *strncat(aa, testet,1));
printf(" aa[0] = %d \n", aa[0]);
printf(" aa[1] = %d \n", aa[1]);
printf(" aa[2] = %d \n", aa[2]);
printf(" aa[3] = %d \n", aa[3]);
Returns:
aaconcat as a 32b word is 1
aaconcat as a 32b word is 1
aa[0] = 1
aa[1] = 2
aa[2] = 1
aa[3] = 0
Though I'm expecting {testet[0],testet[1],testet[0]} = 131330.
if you are trying to concatenate the actual bits, which I suspect you may be trying to do given your expected result from {testet[0],testet[1],testet[0]} = 131330, then try something like this to concatenate the chars:
This assumes the chars you want to concatenate are stored in unsigned char chararr[4].
long int chars_in_int = 0;
for (int i = 0; i < 4; i++ ) {
chars_in_int << 8; /* redundant on first loop */
chars_in_int += chararr[i];
}
This will place the chars with the lowest index in chararr in the most significant bits of chars_in_int.

Parsing data from ASCII formatted file in C

I am trying to do what's been done here Read co-ordinates from a txt files using C Program . The data that I am trying to input is in this format:
f 10 20 21
f 8 15 11
. . . .
f 11 12 25
The only difference in my point structure is that I have a an extra char to store the letter in the first column (which may or may not be the letter f). I guess im either declaring my char wrong, or I'm calling it in printf incorrectly. Either way, I only get the first line read and then my program terminates. Any ideas ?
Here is my MWE below
#define FILEPATHtri "/pathto/grid1DT.txt"
#define FILEPATHorg "/pathto/grid1.txt"
#define MAX 4000
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
typedef struct
{
float x;
float y;
float z;
char t[1];
}Point;
int main(void) {
Point *points = malloc( MAX * sizeof (Point) ) ;
FILE *fp ;
fp = fopen( FILEPATHtri,"r");
int i = 0;
while(fscanf(fp, "%s %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<=i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[i].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
return 0;
}
Since there's only 1 char in there, not a string just use a single char in your code:
char t;
}Point;
Then when you read it in:
while(fscanf(fp, "%c %f %f %f ", &points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
I'll note that having an array of 1 char, at the end of a structure, sets you up for the struct hack which might not have been your intentions... A good reason to use just char t instead of char t[1]
Also this line:
for (n=0; n<=i; n++){
Should be
for (n=0; n<i; n++){
One last note... if you wanted to print the character out that you read in the prints at the bottom, you should be using n:
// note your previous code was points[i].t
printf("%c %f %f %f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
Check this
while(fscanf(fp, "%c %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
getch();
return 0;
}
modification are since only a single character is read %s modified to %c also in printf its not points[i].t its points[n].t . Also the limit checking in for loop is also corrected to n<i

Resources