I am trying to count the occurrence of character for a string.
The user has two options:
first, display the result of screen
second, to store the result in a file but the file name will be a string enter also by user
My real problem is that when in comes to scan the name of the file, it does not work.
The part of my code where count[] has integer number represents the occurrence of each character. When I tryed to debug the code it seems like scan step of out[] string array was skipped, and it got uncommon characters like ÿÿtþa.
printf("Enter 1 if you want to output data on screen\nEnter 2 to output data to file : ");
int input;
scanf("%d", &input);
if(input == 1)
{
fprintf(stdout,"%s:\n\"%s\"\n", "characters count in this string", s);
fprintf( stdout, "%-20s%-4s\n", "character", "count");
for(int j = 0; j < 26; j++)
fprintf( stdout, "%-20c%-4d\n", j+65, count[j]);
}//end of if
else if(input == 2)
{
FILE *Ptr;
printf("enter file name : ");
char out[30]= {'\0'};
scanf("%29[^\n]", out);
if( (Ptr = fopen(out,"w")) == NULL)
printf("CAN NOT OPEN FILE\n");
else
{
fprintf(Ptr,"%s:\n\"%s\"\n", "characters count in this string", s);
fprintf( Ptr, "%-20s%-4s\n", "character", "count");
for(int j = 0; j < 26; j++)
fprintf( Ptr, "%-20c%-4d\n", j+65, count[j]);
}//end of else
fclose(Ptr);
}//end of else
}//end of main
Related
#include<stdio.h>
#include<string.h>
#define ROWS 6
#define LENGTH 30
int main (void)
{
int wordcount[ROWS]; // Incraments word count. i.e. Word 1, Word 2, Word 3...
char word[LENGTH]; // Stores users string
for(int i = 1; i < ROWS; i++)
{
if(i == 1)
{
printf("Word %d: ", i);
scanf("%d %s", &wordcount[i], &word[0]); // Input ends here. Prints out the rest of the array with "no" values.
i++;
}
if(i == 2)
{
printf("Word %d: ", i);
scanf("%d %s", &wordcount[i], &word[1]);
i++;
}
if(i == 3)
{
printf("Word %d: ", i);
scanf("%d %s", &wordcount[i], &word[2]);
i++;
}
if(i == 4)
{
printf("Word %d: ", i);
scanf("%d %s", &wordcount[i], &word[3]);
i++;
}
if(i == 5)
{
printf("Word %d: ", i);
scanf("%d %s", &wordcount[i], &word[4]);
}
break;
}
return 0;
}
I've tried multiple loops, changing syntax and placement, but nothing makes sense to me anymore. I AM NOT ALLOWED TO USE POINTERS, GLOBAL VARIABLES, OR ANY OTHER LIB FUNCTIONS BESIDES scanf(), printf(), fgets(), or strlen(). I have to make multiple functions to get user input, reverse the string, and find out whether or not it's a palindrome... but I can't seem to get past part 1.
A few issues ...
Indexes should start from 0 and not 1
The word array needs to be 2D (not 1D)
That is, you want an array of words that has ROWS number of words and each word can be [up to] LENGTH characters.
A simple loop can get all words without any if statements
It's better to use fgets and strlen instead of scanf for input where you prompt the user
Here is the refactored code:
#include <stdio.h>
#include <string.h>
#define ROWS 5
#define LENGTH 100
int
main(void)
{
// length of each word
int wordcount[ROWS];
// Stores users string
char word[ROWS][LENGTH];
for (int i = 0; i < ROWS; i++) {
// prompt the user
printf("Word %d: ", i + 1);
fflush(stdout);
// get the line with the word
if (fgets(word[i],LENGTH,stdin) == NULL)
break;
// get the word length
size_t len = strlen(word[i]);
// strip newline
if ((len > 0) && (word[i][len - 1] == '\n')) {
word[i][len - 1] = 0;
--len;
}
// save the length
wordcount[i] = len;
}
// print the words
for (int i = 0; i < ROWS; ++i)
printf("Word %d is %d bytes: '%s'\n",i + 1,wordcount[i],word[i]);
return 0;
}
I was able to reproduce this by not entered an integer and only the string. This means scanf() fails on the first and the subsequent attempts. Here is a simplified version of your program with error checking:
#include <stdio.h>
#define ROWS 6
#define LENGTH 29
#define str(s) str2(s)
#define str2(s) #s
int main (void) {
int wordcount[ROWS];
char word[LENGTH+1];
for(int i = 0; i < ROWS; i++) {
printf("Word %d: ", i + 1);
int n = scanf(" %d %" str(LENGTH) "s", wordcount + i, word + i);
if(n != 2) {
printf("scanf failed\n");
break;
}
}
}
and example run:
Word 1: 1 abcd
Word 2: cd
scanf failed
Not clear from the problem description what you are trying to do with word but it's probably incorrect as you write a string to position 0 of word, then the next word 2 at position 1 (overwriting part of word 1) etc. Do you actually mean count of words or count of letters in the word? For the latter use strlen().
So I need output size of array in this file text and to do this I must break the loop in the last position by using NULL to break but the problem here that when arr[i] come to value 0, it equal to NULL and break at that position so my size of array is not complete. How to resolve it? Thanks for support!
The file .txt input:
3
4
0
5
6
The code:
#include <stdio.h>
int main() {
char a[20];
char e[40];
int arr[30];
int num, key, k = 0, len = 0;
printf("Enter a filename: ");
scanf("%s", &a);
scanf("%c", &e);
FILE* rfile;
rfile = fopen(a, "r");
if (rfile == NULL) {
printf("Not found the file !!!");
}
else {
printf("Successfully accessed the file: %s\n", a);
int i;
for (i = 0; i < 30; i++) {
fscanf(rfile, "%d", &arr[i]);
fscanf(rfile, "%c", &e);
if (arr[i] == NULL) { // PROBLEM HERE
break;
}
len++;
}
}
printf("The size of array: %d", len);
return 0;
}
You can find some more details regarding what NULL is here, but you should save NULL for pointer comparisons, not comparing against ints as you are doing. In fact, your usage generates a warning:
warning: comparison between pointer and integer
Despite that, 0 == NULL will evaluate to true. Since 0 is in your list of values, you prematurely break revealing your problem. Instead, you simply need to read the entire file, either until you run out of room in your array (already covered by your for loop) or reach the end of the file (designated by EOF). To determine that, you need to check the return value of fscanf. Below is an example of a possible implementation:
#include <stdio.h>
#include <stdlib.h>
int main() {
int arr[30];
int len = 0;
FILE* rfile;
rfile = fopen("file.txt", "r");
if (rfile == NULL) {
printf("Not found the file !!!");
exit(-1);
}
else {
int i;
for (i = 0; i < 30; i++) {
// fscanf returns the number of correctly matched items, or
// EOF when the end of the file is reached (or EOF on error)
int ret = fscanf(rfile, "%d", &arr[i]);
// did we get a correct match?
if (ret == 1)
{
// we matched one number as expected, increment len
len++;
}
// did we reach the end of file?
else if (ret == EOF)
{
// EOF can also indicate an error, check errno here to determine if
// an error occurred instead of end of file, if you want
break;
}
}
}
// prints 5 with your input file example
printf("The size of array: %d\n", len);
return 0;
}
I have no idea what you were trying to accomplish with e, so I removed that as well as other unused variables, and hardcoded user input.
arr is the array of ints arr[i] has type int. NULL is a pointer.
If 0 indicated the end of the data (sentinel value) then:
if (arr[i] == 0) break;
or in a short form
if (!arr[i]) break;
I am facing some problem here. Whenever I run this code it asks me about name and date of birth. When I give it, it asks me again until I press Ctrl+D. I want this process to be stop after one time and instead it asks me, do you want to continue? If I say yes then it repeat the loop and again ask me one more time. How to do this? I tried but failed.
int main(void){
const char *listing[] = {"Name", "Date of birth"};
char data[2][51];
int done = 0;
FILE *fp;
fp = fopen("/home/bilal/Documents/file.txt", "w+");
while (!done){
for (int i = 0; i < 2; i++){
printf("Enter your %s: ", listing[i]);
if (scanf(" %50[^\n]", data[i]) != 1){
done = 1;
break;
}
}
if (!done){
fprintf(fp, "%s %s\n", data[0], data[1]);
}
}
fclose(fp);
return 0;
}
If I'm interpreting your post correctly, after the first prompt for name and [then] DOB, you want to inject a "Shall I continue?" question.
Here's the refactored code:
#include <stdio.h>
int
domore(void)
{
char buf[51];
int moreflg = -1;
while (moreflg < 0) {
printf("Shall I continue (y/n)? ");
if (scanf(" %50[^\n]", buf) != 1)
break;
switch (buf[0]) {
case 'y':
case 'Y':
moreflg = 1;
break;
case 'n':
case 'N':
moreflg = 0;
break;
}
}
if (moreflg < 0)
moreflg = 0;
return moreflg;
}
int
main(void)
{
const char *listing[] = { "Name", "Date of birth" };
char data[2][51];
int done = 0;
int again = 0;
FILE *fp;
#if 0
fp = fopen("/home/bilal/Documents/file.txt", "w+");
#else
fp = fopen("/tmp/file.txt", "w+");
#endif
while (!done) {
if (again) {
if (! domore())
break;
}
again = 1;
for (int i = 0; i < 2; i++) {
printf("Enter your %s: ", listing[i]);
if (scanf(" %50[^\n]", data[i]) != 1) {
done = 1;
break;
}
}
if (!done) {
fprintf(fp, "%s %s\n", data[0], data[1]);
}
}
fclose(fp);
return 0;
}
scanf() returns the count of parameters successfully matched and formatted, or EOF (-1) in case of an invalid input.
So, the expressions,
char data[1][50]={0};
int val=0;
int count = scanf(" %50[^\n]", data[0]); // 1 parameter to scan and format
will return 1, for a single formatted item.
To get more than 1, you have to scan in, and successfully format more than one item:
count = scanf(" %50[^\n] %d", data[0], &val); //2 parameters to scan and format.
(The return value here will be 2 if successful.)
So, if you change your loop exit criteria to match these expectations, your loop will exit properly.
if (scanf(" %50[^\n]", data[i]) == 1){//now 'done' will be set to true (1)
^^
Edit: Illustrates concepts described above:
(Note, uncomment your file functions, I did not need them for this illustration.)
Program loops until both 'name' and 'date of birth' are captured into a 2D character array. Loop exit criteria uses count of successful, single parameter scanf calls:
int main(void){
const char *listing[] = {"Name", "Date of birth"};
char data[2][51];
int done = 0;
int count = 0;//added to allow visibility of return value of scanf function.
FILE *fp;
//fp = fopen("/home/bilal/Documents/file.txt", "w+");
while (done != 2){
for (int i = 0; i < 2; i++){
printf("Enter your %s: ", listing[i]);
count = scanf(" %50[^\n]", data[i]);
if (count != EOF){
done += count;
// 'break' is not needed here, let the loop leave naturally
}
}
}
if (done == 2)//moved outside of loop because both variables
{ //need to be populated before printing
;//fprintf(fp, "%s %s\n", data[0], data[1]);
}
//fclose(fp);
return 0;
}
The scanf function returns the number of input items success‐fully matched and assigned. So when you type something from the keyboard, the return value of this function is always 1 in your case (you try to input the string, then every character from the keyboard is added to your string).
You can use fgets then compare with the string that content only the enter character "\n" when you want to quit the loop.
printf("Enter your %s: ", listing[i]);
if (strcmp(fgets(data[i], 51, stdin), "\n") == 0){
done = 1;
break;
}
With this code, if you want to quit the while loop, you just have to hit only ENTER.
How can I implement an error check that will loop until a code within a file is entered? This is what I have so far: I have already store each code from the file in an array called array[j].code1.
Here:
printf("Enter item code: "); //Prompts user
scanf ("%14s", codenew1); //Read user input
len = strlen(codenew1); //Read each character into variable len
while (len != strspn(codenew1, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"))
{
printf ("Name contains non-alphabet characters. Try again!: "); //Prompts user to try again
scanf ("%14s", codenew1); //Reads user input
len = strlen(codenew1); //Read each character into variable len
} //Endwhile
strncpy(codenew, codenew1,2); //Copy the first two characters from the variable codenew1
codenew[2] = 0; //Store first two characters into variavle codenew
for ( j = 0; j < num_items; j++) //Loop for num_items times
{ //Beginning of for loop
if (strcmp(array[j].code1, codenew) == 0) //If codenew is found in file
{ //Beginning of if statement
price[i] = item_qty[i] * array[j].price1; //Calculating the price of an item
printf("Price : %d", price[i]); //Prints price
printf("\nEnter '%s' to confirm: ", array[j].itemname1); //Confirming the item
scanf("%19s", item_name1[i]);
while (strcmp(item_name1[i], array[j].itemname1 )!=0) //Looping until both item names are the same
{ //Begin while loop
printf("Item name is not %s ,Try Again!: ", array[j].itemname1); //Prompt user to try again
scanf ("%19s", item_name1[i]); //Reads item name into an array
len = strlen(item_name1[i]); //Reads each character into variable len
} //End while loop
len = strlen(item_name1[i]); //Read each character into variable len
while (len != strspn(item_name1[i], "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) //While len contains non alphabetic characters
{ //Beginning while
printf ("Name contains non-alphabet characters. Try again!: "); //Prompts user to try again
scanf ("%19s", item_name1[i]); //Read user input
len = strlen(item_name1[i]); //Read each character into variable len
} //End while
strncpy(item_name[i], item_name1[i], 20); //Copy the first two characters from the variable codenew1
item_name[i][20] = 0; //Store first 20 characters in variable item_name[i]
total_price+= price[i]; //Calculate total price
break; //Terminates loop
} //End of if statement
else
if (strcmp(array[j].code1, codenew) != 0) //If codenew is found in file
{
printf("Invalid input! Try again.");
goto Here;
}
} //End of for loop
The current structure of the code is
Here:
// get "codenew" from user
for ( j = 0; j < num_items; j++ )
{
if ( strcmp(array[j].code1, codenew) == 0) )
{
// do a whole bunch of stuff
break;
}
else if ( strcmp(array[j].code1, codenew != 0) )
{
printf( "Invalid input! Try again.\n" );
goto Here;
}
}
The behavior of the code is to check the first entry in a list of codes. If the first entry matches the user input, then "whole bunch of stuff" gets executed and the loop breaks. Otherwise, an error message gets printed and the code jumps back to the label Here:. Thus, the user is forced to enter the first code in the list. Any other code just jumps back to the beginning.
I assume that what the code should do is scan the whole list to see if it can find a matching entry. To accomplish that, I would put the code into a subroutine that searches the list and returns 1 if it finds a match, or 0 if no match is found. The function would be called repeatedly until the user enters a valid code. Here's the structure of the proposed function.
int findCode( void )
{
// get "codenew" from user
for ( j = 0; j < num_items; j++ )
{
if ( strcmp(array[j].code1, codenew) == 0) )
{
// do a whole bunch of stuff
return 1; // SUCCESS, the user entered a valid code
}
}
return 0; // FAILED, no matching code in the list
}
Here's how the function would be called. The while loop will keep calling the function until it returns "success".
while ( !findCode() )
printf( "Invalid input! Try again.\n" );
I'm really new to C so it would be great if someone could tell me how I can do this:
I am trying to get user input using fgets. So if the user enters the following integers:
1 2 3 4 5
How do i scan them and put them in an array of ints= [1,2,3,4,5]
Here is what I am trying to do right now: I am continuously looping and asking the user to input a number until the user does not put anything. In each iteration, I am saving the input of the user to the array
int myArray[200];
char input_str[1024];
fprintf(stdout, "Enter numbers: ");
if (fgets(input_str, sizeof(input_str), stdin) == 0){
fprintf(stderr, "Error returned from fgets()...\n");
exit(1);
}
sscanf(input_str, "%d", &n);
myArray[i]=n;
//The while loop will continue as long as the string is not null
while( input_str[0]!='\0'){
if (fgets(input_str, sizeof(input_str), stdin) == 0){
break;
}
for (i=1;i<201;i++){
sscanf(input_str, "%d", &n);
myArray[i]=n;
}
}
#include <stdio.h>
int main(void){
int myArray[200];
char input_str[1024];
int i, n = 0;
size_t full = sizeof(myArray)/sizeof(*myArray);
fprintf(stdout, "Enter numbers: ");
while(fgets(input_str, sizeof(input_str), stdin) != NULL){
char *p = input_str;
int v, len;
if(*input_str == '\n' || n == full)
break;//input end if blank line
while(1==sscanf(p, "%d%n", &v, &len)){
myArray[n++] = v;
p += len;
if(n == full)
break;
}
}
//check print
for (i=0;i<n;i++)
printf("%d ", myArray[i]);
return 0;
}