Read only first character with scanf - c

I am trying to read only the first character of each line using scanf.
With this input:
c FILE: myciel3.col
c SOURCE: Michael Trick (trick#cmu.edu)
c DESCRIPTION: Graph based on Mycielski transformation.
c Triangle free (clique number 2) but increasing
c coloring number
p edge 11 20
Sorry for my bad english.
int main(int argc, char *argv[]) {
char option;
int countC = 0;
int countP = 0;
while(scanf("%c",&option) != EOF) {
if(option == 'c') countC++;
else if (option == 'p') countP++;
}
printf("c: %d\tp: %d\n",countC, countP);
return (0);
}
I expect the output C:5 and P:1, but the actual output is c:15 p:2

Your code reads every character in your input, not the first character of each line.
Use fgets or any other function that gets a line.
#include <stdio.h>
int main(int argc, char *argv[]) {
char option[255];
int countC = 0;
int countP = 0;
while(fgets(option, 255, stdin) != NULL) {
if(option[0] == 'c') countC++;
else if (option[0] == 'p') countP++;
}
printf("c: %d\tp: %d\n",countC, countP);
return (0);
}

Related

Function is not correctly incrementing variable by 1

I have a function that returns the number of lines, characters, and words in an array. For some reason, when i loop through the array to print the values I am only getting the corrrect value for lines, the characters and words are returning as 0. All the functions are predetermined by my professor and my job is to fill them in.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
The best option is probably to just iterate through the file in one loop (you could also rewind() after the first loop). Use the return value of fgetc() to determine of you are at EOF instead of separate feof() calls. I also made the the result array an (out) argument instead of using a static variable (the latter is not reentrant if you ever want to call this from multiple threads and it's easy to do):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if(c == EOF)
break;
else if(c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
The output on the above file is:
39
94
715
The word count 94 doesn't agree with wc -w but you could be using a different definition of what a word is.
It's a good idea to separate calculations and i/o, so consider opening and closing the file in main() and pass in the file handle. It becomes easy, for instance, to use the stdin file handle instead if you don't want to use a physical file.
After the first do-while loop the condition EOF occurs.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
So the following while loop has no effect.
You should use only one loop to count lines, words and characters.
Pay attention to that the variable c should be declared as having the type int
int c;
Also you need to exit the function if the file was not opened.

running the program doesn't print the second printf statement

whenever I run the program the second print statement isn't printing. I tried using a function but I'm new to C and don't really understand anything. I've also attached my activity as I'm not sure how to do the other things on it.activity photo
#include <stdio.h>
#include <string.h>
#define LINE_LENGTH 1000
int main(int argc, char **argv)
{
FILE *input_file = fopen("cstest.c", "r");
char line [LINE_LENGTH];
//while loop to ger
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
ch = fgetc(input_file);
if (ch == '\n')
{
lines++;
}
}//end while
printf("lines: %d\n", lines);
}//end while loop
while (fgets(line, LINE_LENGTH, input_file) != NULL)
{
int ch = 0;//ch is the cast
int lines = 0;//start with one because
if (input_file == NULL)
return 0;
while (!feof(input_file))
{
int characters = 0;
char c;
for (c = getc(input_file); c != EOF; c = getc(input_file))
// Increment count for this character
characters = characters + 1;
printf("characters: %d\n", characters);
fclose(input_file);
}
}
}

How to check for a blank space with scanf("%s", answer)

So, I'm working on this program and I've encountered a problem with scanf. I'm scanning the input from the user in the form of a string, however if the user just presses enter, scanf doesn't pick up on it and the cursor just moves on waiting for whatever specified input I programmed it to look for. Is there anyway I can skirt around this with like a comparison to 0 or 1, or do I need to go about this in another way? Yes, this is the same program from earlier and I thought to mention this in the other post I made, but I figured this was a different problem in itself so it deserved another post separate from my other problem earlier.
/*
* Scott English
* CS 1412
* tconv
* 1/28/15
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *
input_from_args(int argc, const char *argv[])
{
if (argc == 1){
return stdin;
}
else {
return fopen(argv[1], "r");
}
}
void
rot_13(FILE *src, FILE *dest)
{
int c,j;
while ((c = getc(src)) != EOF)
{
if(c>= 'A' && c <= 'Z')
{
if((j = c + 13) <= 'Z')
c = j;
else
{
j = c - 13;
c = j;
}
}
else if(c >= 'a' && c <= 'z')
{
if((j = c + 13) <= 'z')
c = j;
else
{
j = c - 13;
c = j;
}
}
else
c = c;
fprintf(dest, "%c", c);
}
}
void
convert_all_upper(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", toupper(c));
}
}
void
convert_all_lower(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", tolower(c));
}
}
void
print_all(FILE *src, FILE *dest)
{
int c;
while ((c = fgetc(src)) != EOF)
{
fprintf(dest, "%c", c);
}
}
int
main(int argc, const char *argv[])
{
char answer[4];
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
printf("Please enter which conversion -r -u -l\n");
scanf("%s", answer);
if (src == NULL)
{
fprintf(stderr, "%s: unable to open %s\n", argv [0], argv[1]);
exit(EXIT_FAILURE);
}
else if (strcmp(answer,"-r") == 0)
{
rot_13(src, dest);
}
else if (strcmp(answer, "-u") == 0)
{
convert_all_upper(src, dest);
}
else if (strcmp(answer, "-l") == 0)
{
convert_all_lower(src, dest);
}
else
{
printf("%s: is unsupported\n", answer);
}
fclose(src);
return EXIT_SUCCESS;
}
ESTRAPOLATED FROM LINK
scanf stands for "scan formatted" and there's precious little less formatted than user-entered data. It's ideal if you have total control of the input data format but generally unsuitable for user input.
Use fgets() to get your input into a string and sscanf() to evaluate it.
A simple program to show you how to intercept the 'enter' key.
#include<stdio.h>
#include<string.h>
int main()
{
char answer[4];
memset(answer, 0x00, sizeof(answer));
printf("Please enter which conversion -r -u -l\n");
fgets (answer, sizeof(answer), stdin);
if (strlen(answer) > 0)
{
if (answer[0] == '\n')
{
printf("Empty string and enter key pressed\n");
}
else
{
printf("Parameter %s", answer);
}
}
return 0;
}
I recommend using fgets:
fgets(answer, sizeof answer, stdin);
instead of scanf, since scanf skips over whitespace including newlines, and the user won't be able to get out of the input loop.
"if the user just presses enter, scanf doesn't pick up on it" -->
scanf("%s", answer) is just beginning.
The "%s" specifies scanf() to scan 3 things:
1) Scan in and toss all leading white-space including '\n', ' ', '\t' and a few others.
2) Scan in and save an unlimited number of non-white-space char to answer. Append a terminating '\0' when done.
3) Upon scanning a white-space again, put that char back into stdin for later reading.
So when a user enters Enter or '\n', scanf("%s", answer) is still in step 1.
As a rule: mixing scanf() with fgets()/getc() is problematic. Further recommend against using scanf() for just about all applications. Consider:
// char answer[4];
// scanf("%s", answer);
char answer[4+1];
if (fgets(answer, sizeof answer, stdin) == NULL) return 1; // stdin closed
// now remove the potential trailing '\n`.
size_t len = strlen(answer);
if (len > 0 && answer[len-1] == '\n') answer[--len] = 0;

string in place of int in c

//why the code starts printing retry infinitely if i wrongly
enter a string in place of int i in terminal
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char const *argv[])
{
int i,j=0;
while(1)
{
scanf("%d",&i);
if(i==10)
{
printf("you got the max! YOU WON\n");
break;
}
else
{
printf("%s\n","retry" );
}
}
return 0;
}
Try consuming (flushing) on bad input:
else {
while ((j = fgetc(stdin)) != '\n' && j != EOF);
printf("%s\n", "retry");
}
An alternative using fgets (is preferable because it consumes the whole line) and strtol:
#include <stdio.h> /* fgets, printf */
#include <stdlib.h> /* strtol */
#include <string.h> /* strchr */
int main(void) /* No args */
{
char buf[128], *p;
int i;
while (fgets(buf, sizeof(buf), stdin)) {
if ((p = strchr(buf, '\n')) != NULL) {
*p = '\0'; /* remove newline */
}
i = (int)strtol(buf, &p, 10); /* Base 10 */
if (*p != '\0' || i != 10) {
printf("retry\n");
} else {
printf("you got the max! YOU WON\n");
break;
}
}
return 0;
}
Read fails because of you inputted wrong type and i will have garbage value.
Add initialization to i:
int i=0, j=0;
scanf returns number of succesful reads. Add return value check to scanf:
int r = scanf("%d",&i); // Will return 1 if 1 argument was successully read
if(r == 1 && i == 10)
{
//do something
}
Edit:
As others have pointed out, it seems that scanf doesn't consume incoming bytes if input is wrong. Thus you might want to replace it wit fgets and sscanf:
int r;
char temp[32];
fgets(temp, 32, stdin); // Read input to temporary buffer
r = sscanf(temp, "%d", &i); // Try to convert value on buffer
if(r == 1 && i == 10)
{
//do something
}

issue with multifunction utility program in c.

The following program is supposed to read from the command line( using argv[]) and execute either one of three functions:
right(decides whether or not a triangle is a right triangle based on the side length: by typing mu -r [sidea] [sideb] [sidec]
findtext:(finds the sequence of a string inside of a given file: (ie,"hello") and lists the line number where it found it.
count: (counts the number of tabs, words and backspaces).
Findtext.c is functioning as it should:
for example if i type ./mu -f [string] [file.txt]
it successfully list the file and the line number in the file in which it was found.
but when I run the same code with the -r(right) option it gives me the following segmentation fault:
Program name: ./mu
3
Segmentation fault (core dumped)
where am i going wrong in this code?
#include <stdio.h>
#include <stdlib.h>
//#include "count.h"
//#include "right.h"
//#include "findtext.h"
#define STAND_ALONE 1
void right(int, char **);
void count(int, char **);
void findtext(int, char **);
#ifdef STAND_ALONE
int main(int argc, char *argv[])
{
printf("\n");
printf("Can only use one option(-f, -c, -r) at once. sorry!\n");
printf("\n");
printf("Program name: %s\n", argv[0]);
while ((argc > 1) && (argv[1][0] == '-'))
{
switch (argv[1][1])
{
case 'f': // findtext.c
printf("%s\n",&argv[1][2]);
findtext(argc, argv);
break;
case 'r': // right.c
printf("%s\n",&argv[1][2]);
right(argc, argv);
break;
case 'c': // count.c
printf("%s\n",&argv[1][2]);
count(argc,argv);
break;
default:
printf("Wrong Argument: %s\n", argv[1]);
}
++argv;
--argc;
}
return (0);
}
#endif
void right(int argc, char *argv[]){
int a;
int b;
int c;
int largest;
int a2;
int b2;
int c2;
/*if(argc != 4){
printf("please enter 3 sides, only \n");
} */
a = atoi(argv[2]);
b = atoi(argv[3]);
c = atoi(argv[4]);
//printf("argv2:%s ",argv[2]);
if((a <= 0 )|| (b <= 0) || (c <= 0))
printf("Only positive values allowed\n"); exit(0);
a2 = (a*a);
b2 = (b*b);
c2 = (c*c);
if((c > a) && (c > b))
largest = c;
if((b > a) && (b > c))
largest = b;
if((a > b) && (a > c))
largest = a;
if(largest == a){
printf("HEy hey hey!");
if((b2 + c2) == a2){ printf("%s %s %s is a right triangle\n",argv[2],argv[3],argv[4]); }
else{printf("%s %s %s is not a right triangle\n",argv[3],argv[2],argv[4]);}
}
if(largest == b){
printf("HEy");
if((a2 + c2) == b2){ printf("%s %s %s is a right triangle\n",argv[2],argv[3],argv[4]); }
else{printf("%s %s %s is not a right triangle\n",argv[2],argv[3],argv[4]);}
}
if(largest == c){
printf("yo");
if((a2 + b2) == c2){ printf("%s %s %s is a right triangle\n",argv[2],argv[3],argv[4]); }
else{printf("%s %s %s is not a right triangle\n",argv[2],argv[3],argv[4]);}
}
} /* end method right() */
void findtext(int argc, char *argv[]){
FILE *fin;
char buffer[100];
int counter;
char *ptr = buffer;
char *result;
//if(argc != 3) {printf("Usage: %s filename argc:%d\n", argv[0], argc); exit(1);}
fin = fopen(argv[3], "r");
if(!fin) {printf("Unable to open %s\n", argv[2]); exit(1); }
counter = 0;
while (fgets(buffer, 99, fin)){
counter = counter + 1;
if(strstr(ptr,argv[2])){
printf("%d. %s", counter, ptr);
printf("\n");
}
}
fclose (fin);
}
void count(int argc, char **argv){
FILE *fin;
int lcounter = 0;
int count = 0;
char name[100];
char ch;
int word = 0;
int nchar = 0;
fin = fopen(argv[1],"r"); // open file
if(fin==0){
printf("Could not find specified file.\n");
exit(0);
}
while((ch = getc(fin)) != EOF)
{
nchar++;
if(ch == '\n')
lcounter++;
if(isspace(ch) || ch == '\t' || ch == '\n')
word++;
}
printf("number of characters: %d\n",nchar);
printf("Lines: %d\n",lcounter);
printf("words: %d\n",word);
printf("\n");
fclose(fin);
}
if((a <= 0 )|| (b <= 0) || (c <= 0))
printf("Only positive values allowed\n"); exit(0);
Beware to the if-block. You are not using braces. At this point of the right function the program will end, in any case.
Of course this is not the bug you are looking for but it offers a starting point: the bug must necessarily be before this point.
You may need to debug what goes on here:
a = atoi(argv[2]);
b = atoi(argv[3]);
c = atoi(argv[4]);
See #Domenico De Felice answer.
Add #include <string.h>, #include <ctype.h>
You are accessing chars in argv[1] without knowing it is long enough to have those characters. while ((argc > 1) && (argv[1][0] == '-')). printf("%s\n",&argv[1][2]); should print only a line feed as argv[1] is "-r".
in right(), you do c = atoi(argv[4]); without knowing 5 args exist.
please review the need for your interesting code ++argv; --argc;. I really don't think these are going to do what you may want.
I think you are crashing because you do not always put the numbers of arguments (command parameters) that your code hopes to read. Increase your validation of program parameters before using them.
5.
You are crashing because you are trying to increment argv which is an array variable, not a pointer. So you cannot do argv++;
as a good programming principle, (although it is optional) argc, and argv should NOT be touched; you should use point to them using other variables if you want to run through them.
There are many other uglinesses in the code that try to access pointers and addresses without actually confirming whether they are there.
However, to begin with argv is where you are seg-faulting.

Resources