In a file, words like this are written:
Name
Surname
Age
Job
Telephone
James
Cooper
26
engineer
6545654565
Bob
Allen
22
doctor
5656555655
....
I want to print specific parts from these lines (for examples only names). I have tried this code but I can only print 1 line I want. (I print only James but I want to print all names: James, Bob,...).
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int lineNumber;
static const char filename[] = "hayat.txt";
for(lineNumber=5;lineNumber<20;lineNumber+5);
FILE *file = fopen(filename, "r");
int count = 0;
if ( file != NULL )
{
char line[256];
while (fgets(line, sizeof line, file) != NULL)
{
if (count == lineNumber)
{
printf("\n %s ", line);
fclose(file);
return 0;
}
else
{
count++;
}
}
fclose(file);
}
return 0;
}
How can I do this?
I tried to make it work writing the code the most similar to the code in the question. This might not be the optimal solution but should work.
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define TAMLINE 256
int main(void){
int lineNumber, count=0;
static const char filename[] = "hayat.txt";
FILE *file = fopen(filename, "r");
if ( file != NULL ){
char line[TAMLINE];
/* //use this if you want to skip first 5 lines
for(int i=0;i<5;i++){
fgets(line, TAMLINE, file)
}
*/
while (fgets(line, TAMLINE, file) != NULL){
count ++;
//only print 1st line, 6th line 11 line.. ie lines with names
if (count%5 == 1){
printf("%s", line);
}
}
fclose(file);
}
return 0;
}
You only print once because that's exactly what are telling the programm to do
if linenumber == count ... print
else count++
will always print only one line.
As for how to print difference categories, you either find similarities ( like some Objects and all names start with a capital letter and no number) or you specify them in an array - which probably would not be what you would like.
Related
I trying to open a simple txt file in C, like the image bellow.
list example
The input text :
Name Sex Age Dad Mom
Gabriel M 58 George Claire
Louise F 44
Pablo M 19 David Maria
My doubt is, how can i make to identify the blank spaces in the list and jump correctly to another lines.
Here is my code:
#include <stdio.h>
int main() {
FILE *cfPtr;
if ((cfPtr = fopen("clients.txt", "r")) == NULL) {
puts("The file can't be open");
} else {
char name[20];
char sex[4];
int age;
char dad[20];
char mom[20];
char line[300];
printf("%-10s%-10s%-10s%-10s%-10s\n","Name","Sex","Age","Dad","Mom");
fgets(line,300,cfPtr);
fscanf(cfPtr,"%10s%10s%d%12s%12s",name,sex,&age,dad,mom);
while (!feof(cfPtr)) {
printf("%-10s%-10s%d%12s%12s\n",name,sex,age,dad,mom);
fscanf(cfPtr,"%19s%3s%d%12s%12s",name,sex,&age,dad,mom);
}
fclose(cfPtr);
}
return 0;
}
It works fine if I fill in all the spaces...
printf("%-10s%-10s%d%12s%12s\n",name,sex,age,dad,mom);
fscanf(cfPtr,"%19s%3s%d%12s%12s",name,sex,&age,dad,mom);
Change the order to read first, print later.
Ideally the data in your file should be separated by comma, tab, or some other character. If data is in fixed columns, then read everything as text (including integers) then convert the integer to text later.
Also check the return value for fscanf, if the result is not 5 then some fields were missing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *cfPtr = fopen("clients.txt", "r");
if(cfPtr == NULL)
{
puts("The file can't be open");
return 0;
}
char name[11], sex[11], dad[11], mom[11], line[300];
int age;
fgets(line, sizeof(line), cfPtr); //skip the first line
while(fgets(line, sizeof(line), cfPtr))
{
if(5 == sscanf(line, "%10s%10s%10d%10s%10s", name, sex, &age, dad, mom))
printf("%s, %s, %d, %s, %s\n", name, sex, age, dad, mom);
}
fclose(cfPtr);
return 0;
}
Edit, changed sscan format to read integer directly, changed buffer allocation to 11 which is all that's needed.
I'm trying to get two words in a string and I don't know how I can do it. I tried but if in a text file I have 'name Penny Marie' it gives me :name Penny. How can I get Penny Marie in s1? Thank you
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello world!\n");
char s[50];
char s1[20];
FILE* fp = fopen("file.txt", "rt");
if (fp == NULL)
return 0;
fscanf(fp,"%s %s",s,s1);
{
printf("%s\n",s);
printf("%s",s1);
}
fclose(fp);
return 0;
}
Change the fscanf format, just tell it to not stop reading until new line:
fscanf(fp,"%s %[^\n]s",s,s1);
You shall use fgets.
Or you can try to do this :
fscanf(fp,"%s %s %s", s0, s, s1);
{
printf("%s\n",s);
printf("%s",s1);
}
and declare s0 as a void*
The other answers address adjustments to your fscanf call specific to your stated need. (Although fscanf() is not generally the best way to do what you are asking.) Your question is specific about getting 2 words, Penny & Marie, from a line in a file that contains: name Penny Marie. And as asked in comments, what if the file contains more than 1 line that needs to be parsed, or the name strings contain a variable number of names. Generally, the following functions and techniques are more suitable and are more commonly used to read content from a file and parse its content into strings:
fopen() and its arguments.
fgets()
strtok() (or strtok_r())
How to determine count of lines in a file (useful for creating an array of strings)
How to read lines of file into array of strings.
Deploying these techniques and functions can be adapted in many ways to parse content from files. To illustrate, a small example using these techniques is implemented below that will handle your stated needs, including multiple lines per file and variable numbers of names in each line.
Given File: names.txt in local directory:
name Penny Marie
name Jerry Smith
name Anthony James
name William Begoin
name Billy Jay Smith
name Jill Garner
name Cyndi Elm
name Bill Jones
name Ella Fitz Bella Jay
name Jerry
The following reads a file to characterize its contents in terms of number of lines, and longest line, creates an array of strings then populates each string in the array with names in the file, regardless the number of parts of the name.
int main(void)
{
// get count of lines in file:
int longest=0, i;
int count = count_of_lines(".\\names.txt", &longest);
// create array of strings with information from above
char names[count][longest+2]; // +2 - newline and NULL
char temp[longest+2];
char *tok;
FILE *fp = fopen(".\\names.txt", "r");
if(fp)
{
for(i=0;i<count;i++)
{
if(fgets(temp, longest+2, fp))// read next line
{
tok = strtok(temp, " \n"); // throw away "name" and space
if(tok)
{
tok = strtok(NULL, " \n");//capture first name of line.
if(tok)
{
strcpy(names[i], tok); // write first name element to string.
tok = strtok(NULL, " \n");
while(tok) // continue until all name elements in line are read
{ //concatenate remaining name elements
strcat(names[i], " ");// add space between name elements
strcat(names[i], tok);// next name element
tok = strtok(NULL, " \n");
}
}
}
}
}
}
return 0;
}
// returns count, and passes back longest
int count_of_lines(char *filename, int *longest)
{
int count = 0;
int len=0, lenKeep=0;
int c;
FILE *fp = fopen(filename, "r");
if(fp)
{
c = getc(fp);
while(c != EOF)
{
if(c != '\n')
{
len++;
}
else
{
lenKeep = (len < lenKeep) ? lenKeep : len;
len = 0;
count++;
}
c = getc(fp);
}
fclose(fp);
*longest = lenKeep;
}
return count;
}
Change your fscanf line to fscanf(fp, "%s %s %s", s, s1, s2).
Then you can printf your s1 and s2 variables to get "Penny" and "Marie".
Try the function fgets
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
if( fgets (str, 60, fp)!=NULL ) {
/* writing content to stdout */
puts(str);
}
fclose(fp);
In the above piece of code it will write out the content with the maximum of 60 characters. You can make that part dynamic with str(len) if I'm not mistaken.
So what I'm basically doing here is using a command line argument to open a file but only open it 4 lines at a time, then a prompt to print out add'l lines. I can get the file to print out but I cannot figure out how to get it to only print out a few lines at a time. This is where I'm at....thoughts?
#include <stdio.h>
int main(int argc, char *argv[])
{
char line[1000];
FILE *pt;
pt = fopen(argv[1], "r");
if(pt == NULL) return -1;
printf(argv[1], line);
while(fgets(line, 1000, pt) != NULL)
printf("%s", line);
fclose(pt);
return 0;
}
I start from strange line of your code, and then I will try to answer the question.
Statement
printf(argv[1], line);
make me curious - what you what to print, actually?
Here line is not initialized, and argv[1] can hardly be used as format line.
So I suppose it should be just
printf(argv[1]);
or
printf("Filename is %s\n", argv[1]);
As for reading from a file with name provided as argv[1] your code looks able to work, I mean your code read line by line till the end of file and prints these lines at the screen.
If you want to change this logic, e.g. read only 4 first line, add condition with counter, e.g.:
int cnt;
for (cnt = 0; cnt < 4; cnt++) // repeat reading 4 times
{
if (fgets(line, 1000, pt) != NULL)
printf("%s", line);
else
break; // stop when reading fails
}
or (I prefer this version)
int cnt = 0;
while (fgets(line, 1000, pt) != NULL && cnt < 4)
{
printf("%s", line);
cnt++;
}
Such changes allows to stop reading (as well as output), so only 4 or less lines will be shown at console screen.
Finally, for case when you want to show file by groups of 4 (or other constant value), consider the following snippet:
#include <stdio.h>
#define MAX_LINES_TO_PRINT 4
int main(int argc, char *argv[])
{
char line[1000];
FILE *pt;
pt = fopen(argv[1], "r");
if (pt == NULL) return -1;
printf("Filename is %s\n", argv[1]);
int cnt = 0;
while (fgets(line, 1000, pt) != NULL)
{
printf("%s", line);
cnt++;
if (cnt % MAX_LINES_TO_PRINT == 0)
{
int answer;
printf("[%d lines printed] Continue? (Y/N) : ", cnt);
answer = getchar(); // get user's response
while (getchar() != '\n'); // clean input buffer after getchar
if (toupper(answer) == 'N')
{
break; // stop reading the file
}
}
}
fclose(pt);
return 0;
}
Try this program with your file and ask question if something is unclear.
Changing the value in the line #define MAX_LINES_TO_PRINT 4 you can regulate maximum number of lines printed at once (before the next request to continue), e.g. #define MAX_LINES_TO_PRINT 15 make your program printing up to 15 lines.
I have created a function that takes as a parameter the name of a source file, the name of a destination file and the beginning and end lines of the source file lines that will be copied to the destination file, like the example below. All I want to do is to input the lines that I want to copy to the other text file like the example below:
The code I show you just "reads" the content of the one text file and "writes" another one. I want to "write" specific lines that the user gives, not the whole text file
Inputs by the user:
Source_file.txt //the file that the destination file will read from
destination_file.txt //the new file that the program has written
2 3 // the lines that it will print to the destination file: 2-3
Source_file.txt:
1
2
3
4
5
6
destination_file.txt
2
3
code:
#include <stdio.h>
#include <stdlib.h>
void cp(char source_file[], char destination_file[], int lines_copy) {
char ch;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("File name not found, make sure the source file exists and is ending at .txt\n");
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
fclose(source);
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF)
fputc(ch, destination);
printf("Copied lines %d from %s to %s \n",
lines_copy, source_file, destination_file, ".txt");
fclose(source);
fclose(destination);
}
int main() {
char s[20];
char d[20];
int lines;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the number of lines you want to copy\n\n");
printf(">subcopy.o ");
gets(s);
printf("destination file-> ");
gets(d);
printf("Lines: ");
scanf("%d", &lines);
cp(s, d, lines);
return 0;
}
In cp(), in order to select the lines to keep, you have to know their position in the input-file. Thus, you need to count lines.
Using fgets instead of fgetc will allow you to count the lines.
On the other hand, if I wanted to select lines 3 and 7 to 12 in a file, I'd use:
sed -n -e "3p;7,12p" < input.txt > output.txt
this is a very simple solution, let's say you know that the maximun length of a line will be 100 characters for simplicity (if a line is longer than 100 characters only the first 100 will be taken)
at the top (outside main) you can write
#ifndef MAX_LINE_SIZE
#define MAX_LINE_SIZE 100
#endif
i know many people don't like this but i think in this case it makes the code more elegant and easier to change if you need to modify the maximum line size.
to print only the wanted lines you can do something like this
char line[MAX_LINE_SIZE];
int count = 0;
while (fgets(line, MAX_LINE_SIZE, source)){
count++;
if (3 <= count && count <= 5){
fputs(line, destination);
}
}
The while loop will end when EOF is reched because fgets returns NULL.
P.S. there could be some slight errors here and there since i wrote it pretty fast and going by memory but in general it should work.
There are some problems in your program:
Do not use gets(), it may cause buffer overflows.
Always use type int to store the return value of fgetc() in order to distinguish EOF from regular byte values.
You pass an extra argument ".txt" to printf(). It will be ignored but should be removed nonetheless.
To copy a range of lines from source to destination, you can just modify your function this way:
#include <stdio.h>
#include <string.h>
#include <errno.h>
void cp(char source_file[], char destination_file[], int start_line, int end_line) {
int ch;
int line = 1, lines_copied;
FILE *source, *destination;
source = fopen(source_file, "r");
if (source == NULL) {
printf("Cannot open input file %s: %s\n",
source_file, strerror(errno));
exit(EXIT_FAILURE);
}
destination = fopen(destination_file, "w");
if (destination == NULL) {
printf("Cannot open output file %s: %s\n",
destination_file, strerror(errno));
fclose(source);
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF) {
if (line >= start_line && line <= end_line) {
fputc(ch, destination);
}
if (ch == '\n') {
line++;
}
}
lines_copied = 0;
if (line > start_line) {
if (line >= end_line) {
lines_copied = end_line - start_line + 1;
} else {
lines_copied = line - start_line + 1;
}
}
printf("Copied lines %d from %s to %s\n",
lines_copy, source_file, destination_file);
fclose(source);
fclose(destination);
}
int main() {
char source_file[80];
char destination_file[80];
int start_line, end_line;
printf("-Enter the name of the source file ending in .txt\n"
"-Enter the name of the destination file ending in .txt\n"
"-Enter the start and end line\n\n");
printf(">subcopy.o ");
if (scanf("%79s", source_file) != 1) {
return 1;
}
printf("destination file-> ");
if (scanf("%79s", destination_file) != 1) {
return 1;
}
printf("Start and end lines: ");
if (scanf("%d %d", &start_line, &end_line) != 2) {
return 1;
}
cp(source_file, destination_file, start_line, end_line);
return 0;
}
My task is to find word palindromes in a text file and to NOT print them into results file. The results file should only contain all the spaces and words that are NOT palindromes. I've been working on this program for two solid weeks, but as I am a total newb in C, I can't simply imagine how to do this correctly. Also, I have to work in Linux environent, so I can't use commands like strrev() which would make my life a lot easier at this point...
Anyways, data file contains a lot of words in a lot of lines separated by quite a few spaces.
Here is the program that is working, but doesn't work with any spaces, because I don't know how to check them at the needed place.
#include <stdio.h>
#include <string.h>
const int CMAX = 1000;
const int Dydis = 256;
FILE *dataFile;
FILE *resFile;
void palindrome(char *linex);
int main(){
char duom[CMAX], res[CMAX], linex[Dydis];
printf("What's the name of data file? \n");
scanf("%s", duom);
dataFile=fopen(duom, "r");
if (dataFile==NULL){
printf ("Error opening data file \n");
return 0;
};
printf("What's the name of results file? \n");
scanf ("%s", res);
resFile=fopen(res, "w");
if (resFile==NULL){
printf ("Error opening results file \n");
return 0;
};
while (fgets(linex, sizeof(linex), dataFile)) {
palindrome(linex);
}
printf ("all done!");
fclose(dataFile);
fclose(resFile);
}
void palindrome(char *linex){
int i, wordlenght, j;
j = 0;
char *wordie;
const char space[2] = " ";
wordie = strtok(linex, space);
while ( wordie != NULL ) {
wordlenght = strlen(wordie);
if (wordie[j] == wordie[wordlenght-1]) {
for (i = 0; i < strlen(wordie); i++) {
if (wordie[i] == wordie[wordlenght-1]) {
if (i == strlen(wordie)-1) {
fprintf(resFile,"");
}
wordlenght--;
}
else {
fprintf(resFile,"%s", wordie);
break;
}
}
}
else {
fprintf(resFile,"%s", wordie);
}
wordie = strtok(NULL, space);
}
}
EDIT:
Code below works as following:
input file is read char by char
if char read isn't alphanumeric, then it is written to the output file
else, the whole word is read with fscanf
if word is not a palindrome, then write to the output file
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int is_pal(char* word) {
size_t len = strlen(word);
char* begin = word;
char* end = word + len - 1;
if (len == 1) {
return 1;
}
while (begin <= end) {
if (*begin != *end) {
return 0;
}
begin++;
end--;
}
return 1;
}
int main(void)
{
FILE* fin = fopen("pals.txt", "r");
if (fin == NULL) {
perror("fopen");
exit(1);
}
FILE* fout = fopen("out_pals.txt", "w");
if (fout == NULL) {
perror("fopen");
exit(1);
}
int ret;
char word[100];
while ((ret = fgetc(fin)) != EOF) {
if (!isalpha(ret)) {
fprintf(fout, "%c", ret);
}
else {
ungetc(ret, fin);
fscanf(fin, "%s", word);
if (!is_pal(word)) {
fprintf(fout, "%s", word);
}
}
}
fclose(fin);
fclose(fout);
return 0;
}
I've created file with following content:
cancer kajak anna sam truck
test1 abc abdcgf groove void
xyz annabelle ponton belowoleb thing
cooc ringnir
The output file :
cancer sam truck
test1 abc abdcgf groove void
xyz annabelle ponton thing
(line with two spaces)
As you can see, the number of spaces between words are the same as in the input file.
I've assumed that single word could have 100 chars maximum. If there would be longer words, reading with fscanf onto fixed-size buffer can be harmful.
Hints:
strtok() gives you a pointer to the start of delimited words but it does not
extract them or put them in their own string for you.
You need some logic to find the end of each word. The function
strlen() will tell you how many characters there are from the char*
that it gets until a null-character. If you give it a pointer to the start
of a word within a sentence it will give you the length from the start of the
word to the end of the sentence.
Breaking palindrome() into a function that loops over words in a line and a
function that returns whether or not a single word is a palindrome
may help.
Your for loop is checking each pair of letters twice. i only needs to scan over half
of the word length.
You only need a single if within palindrome(). I'm not sure why you have so many.
They're redundant.