I want to take input from a file to my c program. The input should consists of Numbers and characters thereafter i want to differentiate both of them. As fscanf returns 0 when it encounters a non integers, it not worthy of being used here, what to do?
#include <stdio.h>
#include <ctype.h>
int main(){
int num, status;
FILE *fp = fopen("data.txt", "r");
while(EOF!=(status = fscanf(fp, "%d", &num))){
if(status == 1){
printf("%d\n", num);
} else { //if(status == 0){
(void)fgetc(fp);//replace by #chux's suggestion
int ch;
while(EOF!=(ch=fgetc(fp)) && ch != '-' && !isdigit(ch));
if(ch == '-'){
int pch = fgetc(fp);
if(isdigit(pch)){
ungetc(pch, fp);
ungetc(ch, fp);
}
} else {
ungetc(ch, fp);
}
}
}
fclose(fp);
return 0;
}
simply just read the file one by one character at a time and check the range of the value as we know the value in integer value of '0' to '9' is from 48 to 57, just check and use.
Hope it will helps you.
Related
I try to count the number of characters, words, lines in a file.
The txt file is:
The snail moves like a
Hovercraft, held up by a
Rubber cushion of itself,
Sharing its secret
And here is the code,
void count_elements(FILE* fileptr, char* filename, struct fileProps* properties) // counts chars, words and lines
{
fileptr = fopen(filename, "rb");
int chars = 0, words = 0, lines = 0;
char ch;
while ((ch = fgetc(fileptr)) != EOF )
{
if(ch != ' ') chars++;
if (ch == '\n') // check lines
lines++;
if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0') // check words
words++;
}
fclose(fileptr);
properties->char_count = chars;
properties->line_count = lines;
properties->word_count = words;
}
But when i print the num of chars, words and lines, outputs are 81, 18, 5 respectively
What am i missing?
(read mode does not changes anything, i tried "r" as well)
The solution I whipped up gives me the same results as the gedit document statistics:
#include <stdio.h>
void count_elements(char* filename)
{
// This can be a local variable as its not used externally. You do not have to put it into the functions signature.
FILE *fileptr = fopen(filename, "rb");
int chars = 0, words = 0, lines = 0;
int read;
unsigned char last_char = ' '; // Save the last char to see if really a new word was there or multiple spaces
while ((read = fgetc(fileptr)) != EOF) // Read is an int as fgetc returns an int, which is a unsigned char that got casted to int by the function (see manpage for fgetc)
{
unsigned char ch = (char)read; // This cast is safe, as it was already checked for EOF, so its an unsigned char.
if (ch >= 33 && ch <= 126) // only do printable chars without spaces
{
++chars;
}
else if (ch == '\n' || ch == '\t' || ch == '\0' || ch == ' ')
{
// Only if the last character was printable we count it as new word
if (last_char >= 33 && last_char <= 126)
{
++words;
}
if (ch == '\n')
{
++lines;
}
}
last_char = ch;
}
fclose(fileptr);
printf("Chars: %d\n", chars);
printf("Lines: %d\n", lines);
printf("Words: %d\n", words);
}
int main()
{
count_elements("test");
}
Please see the comments in the code for remarks and explanations. The code also would filter out any other special control sequences, like windows CRLF and account only the LF
Your function takes both a FILE* and filename as arguments and one of them should be removed. I've removed filename so that the function can be used with any FILE*, like stdin.
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
typedef struct { /* type defining the struct for easier usage */
uintmax_t char_count;
uintmax_t word_count;
uintmax_t line_count;
} fileProps;
/* a helper function to print the content of a fileProps */
FILE* fileProps_print(FILE *fp, const fileProps *p) {
fprintf(fp,
"chars %ju\n"
"words %ju\n"
"lines %ju\n",
p->char_count, p->word_count, p->line_count);
return fp;
}
void count_elements(FILE *fileptr, fileProps *properties) {
if(!fileptr) return;
properties->char_count = 0;
properties->line_count = 0;
properties->word_count = 0;
char ch;
while((ch = fgetc(fileptr)) != EOF) {
++properties->char_count; /* count all characters */
/* use isspace() to check for whitespace characters */
if(isspace((unsigned char)ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
}
int main() {
fileProps p;
FILE *fp = fopen("the_file.txt", "r");
if(fp) {
count_elements(fp, &p);
fclose(fp);
fileProps_print(stdout, &p);
}
}
Output for the file you showed in the question:
chars 93
words 17
lines 4
Edit: I just noticed your comment "trying to count only alphabetical letters as a char". For that you can use isalpha and replace the while loop with:
while((ch = fgetc(fileptr)) != EOF) {
if(isalpha((unsigned char)ch)) ++properties->char_count;
else if(isspace((unsigned char)ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
Output with the modified version:
chars 74
words 17
lines 4
A version capable of reading "wide" characters (multibyte):
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <wchar.h>
#include <wctype.h>
typedef struct {
uintmax_t char_count;
uintmax_t word_count;
uintmax_t line_count;
} fileProps;
FILE* fileProps_print(FILE *fp, const fileProps *p) {
fprintf(fp,
"chars %ju\n"
"words %ju\n"
"lines %ju\n",
p->char_count, p->word_count, p->line_count);
return fp;
}
void count_elements(FILE *fileptr, fileProps *properties) {
if(!fileptr) return;
properties->char_count = 0;
properties->line_count = 0;
properties->word_count = 0;
wint_t ch;
while((ch = fgetwc(fileptr)) != WEOF) {
if(iswalpha(ch)) ++properties->char_count;
else if(iswspace(ch)) {
++properties->word_count;
if(ch == '\n') ++properties->line_count;
}
}
}
int main() {
setlocale(LC_ALL, "sv_SE.UTF-8"); // set your locale
FILE *fp = fopen("the_file.txt", "r");
if(fp) {
fileProps p;
count_elements(fp, &p);
fclose(fp);
fileProps_print(stdout, &p);
}
}
If the_file.txt contains one line with öäü it'll report
chars 3
words 1
lines 1
and for your original file, it'd report the same as above.
In this program, how i do at the same time convert the uppercase letters to lowercase letters and lowercase letters to uppercase letter?
I have tried many times but it is not working.
My expectations, Suppose for example
Input:
from read.txt(orginal contant of the file:
Hello World)
Output
hELLO wORLD
This is my code....
(I can only convert from uppercase to lowercase. At the same time I could not convert from uppercase to lowercase and lowercase to uppercase).
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE* file;
char ch;
file = fopen("read.txt","r");
while (ch != EOF)
{
ch = toupper(ch);
printf("%c", ch);
ch = fgetc(file);
}
fclose(file);
return 0;
}
you have plenty errors here.
your first check the not initialized ch variable, you use it and try to print, then you read it. The order has to be right opposite.
ch has to be of type int to accommodate EOF
you need to check if the fopen was successful
int main()
{
FILE* fptr;
int ch;
fptr = fopen("read.txt","r");
if(fptr)
{
while ((ch = fgetc(fptr)) != EOF)
{
ch = toupper(ch);
printf("%c", ch);
}
fclose(fptr);
}
return 0;
}
// Note that UPPER and lower chars differ by bit 5 (value 0x20).
// If you want to switch case for any [A-Za-z] in one step,
// an exclusive-OR (^ bitwise operator) can be used:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define TOGGLE_CASE(c) ((c) ^ 0x20)
int
main(void)
{
FILE *file;
char ch;
if ((file = fopen("read.txt", "r")) == NULL) {
dprintf(2, "fopen error\n");
return (1);
}
while ((ch = fgetc(file)) != EOF)
printf("%c", isalpha(ch) ? TOGGLE_CASE(ch) : ch);
fclose(file);
return (0);
}
it's about reading from a text file.
I have 3 command line arguments:
name of text file
delay time
how many line(s) want to read.
I want to read that text file by user specified line numbers till text file ends.
For example, the first time I read 5 lines and then the program asks how many line(s) do you want to read?. I would enter 7 it reads lines 5 to 12.
This would repeat until the end of the file.
#include <stdlib.h>
#include <stdio.h>
#include<time.h>
#include <string.h>
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
int main(int argc, char *arg[])
{
FILE *ptDosya;
char ch;
ch = arg[1][0];
int s2;
int satir = 0;
int spaceCounter=0;
int lineCount, x = 0;
lineCount = atoi(arg[3]);
s2 = atoi(arg[2]);
printf("dosya %d satir icerir.\n", countlines(arg[1]));
ptDosya = fopen(arg[1], "r");
if (ptDosya != NULL)
{
while (ch != EOF&& x < lineCount)
{
ch = getc(ptDosya);
printf("%c", ch);
if (ch == '\n')
{
delay(s2);
x++;
}
}
while (x < countlines(arg[1]))
{
printf("satir sayisi giriniz:");
scanf("%d", &lineCount);
// i don't know what should i do in this loop..
x=x+lineCount;
}
}
else {
printf("dosya bulunamadi");
}
printf("\n\nend of file!\n");
fclose(ptDosya);
return 0;
system("PAUSE");
}
Your delay function uses a busy loop. This is unnecessarily expensive in terms of computing power. It would be very unwelcome to do this on a battery operated device. Furthermore, clock() does not necessarily return a number of milliseconds. The unit used by the clock() function can be determined using the CLOCKS_PER_SEC macro. Unfortunately, there is no portable way to specify a delay expressed in milliseconds, POSIX conformant systems have usleep() and nanosleep().
Your line counting function is incorrect: you count 1 line too many, unless the file ends without a trailing linefeed.
Here is an improved version:
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
There are issues in the main() function too:
You so not verify that enough arguments are passed on the command line.
You do not check for EOF in the main reading loop.
You do not repeat the process in a loop until end of file, nor do you even ask the question how many line(s) do you want to read? after reading the specified number of lines...
First, if the file cannot be found, the countlines method returns zero. You should use that value to write the error message, and skip the rest of the code.
Second, in the next loop, you use
if (ch != '\n') {
printf("%c", ch);
} else {
printf("\n");
delay(s2);
x++;
}
Why the two printf statements? They will print the same thing.
Perhaps something like this:
ch = getc(ptDosya);
/* exit the loop here if you hit EOF */
printf("%c", ch); /* Why not putc() or putchar() ? */
if (ch == '\n') {
x++;
if ( x == lineCount ) {
x = 0;
lineCount = requestNumberOfLinesToRead();
} else {
sleep(s2); /* instead of delay(). Remember to #include unistd.h */
}
}
I'm trying to do this exercise for my exam tomorrow.
I need to compare a string of my own input and see if that string is appearing on the file. This needs to be done directly on the file, so I cannot extract the string to my program and compare them "indirectly".
I found this way but I'm not getting it right, and I don't know why. The algorithm sounds good to me.
Any help, please? I really need to focus on this one.
Thanks in advance, guys.
#include<stdio.h>
void comp();
int main(void)
{
comp();
return 0;
}
void comp()
{
FILE *file = fopen("e1.txt", "r+");
if(!file)
{
printf("Not possible to open the file");
return;
}
char src[50], ch;
short i, len;
fprintf(stdout, "What are you looking for? \nwrite: ");
fgets(src, 200, stdin);
len = strlen(src);
while((ch = fgetc(file)) != EOF)
{
i = 0;
while(ch == src[i])
{
if(i <= len)
{
printf("%c - %c", ch, src[i]);
fseek(file, 0, SEEK_CUR + 1);
i++;
}
else break;
}
}
}
Your logic after matching the first character looks suspect. There's no need to seek in the file, you need to read more content to try to match the later bytes from src and resetting i on each iteration prevents you from checking later characters from src.
The following (untested) code should be closer to the mark
i = 0;
while((ch = fgetc(file)) != EOF) {
if (ch != src[i]) {
i = 0;
}
else if (++i >= len) {
printf("found %s in file\n", src);
break;
}
}
It relies on repeated calls to fgetc rather than fseek and only resets the index into src when a character doesn't match.
Note also that
char src[50];
fgets(src, 200, stdin);
is slightly wrong. It tells fgets that it can write up to 200 chars to src. Writing any more than 50 will write beyond the memory allocated for src, with undefined consequences. You should change this to
char src[50];
fgets(src, sizeof(src), stdin);
while((ch = fgetc(file)) != EOF)
{
if(ch != compare[i]){
i = 0;
}
else{
i++;
}
if(i >= strlen(compare){
printf("we have a match");
break;
}
}
Currently I am trying to read a UTF-16 encoded CSV file char by char, and convert each char into ascii so I can process it. I later plan to change my processed data back to UTF-16 but that is besides the point right now.
I know right off the bat I am doing this completely wrong, as I have never attempted anything like this before:
int main(void)
{
FILE *fp;
int ch;
if(!(fp = fopen("x.csv", "r"))) return 1;
while(ch != EOF)
{
ch = fgetc(fp);
ch = (wchar_t) ch;
ch = (char) ch;
printf("%c", ch);
}
fclose(fp);
return 0;
}
Wishfully thinking, I was hoping that that work by magic for some reason but that was not the case. How can I read a UTF-16 CSV file and convert it to ascii? My guess is since each utf-16 char is two bytes (i think?) I'm going to have to read two bytes at a time from the file into a variable of some datatype which I am not sure of. Then I guess I will have to check the bits of this variable to make sure it is valid ascii and convert it from there? I don't know how I would do this though and any help would be great.
You should use fgetwc. The below code should work in the presence of a byte-order mark, and an available locale named en_US.UTF-16.
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
main() {
setlocale(LC_ALL, "en_US.UTF-16");
FILE *fp = fopen("x.csv", "rb");
if (fp) {
int order = fgetc(fp) == 0xFE;
order = fgetc(fp) == 0xFF;
wint_t ch;
while ((ch = fgetwc(fp)) != WEOF) {
putchar(order ? ch >> 8 : ch);
}
putchar('\n');
fclose(fp);
return 0;
} else {
perror("opening x.csv");
return 1;
}
}
This is my solution thanks to the comments under my original question. Since every character in the CSV file is valid ascii the solution was simple as this:
int main(void)
{
FILE *fp;
int ch, i = 1;
if(!(fp = fopen("x.csv", "r"))) return 1;
while(ch != EOF)
{
ch = fgetc(fp);
if(i % 2) //ch is valid ascii
i++;
}
fclose(fp);
return 0;
}