I am trying to master working with files in C, and I have a bump which I can't pass. I have been searching all day for information but I can't seem to find what I am looking for. I would like to number the lines in a file. For example, if I type in information about a book (let's say: Name, Air-date and id), I would expect something like this in my file:
1. Name:Dave Air-Date:1997 id:123
And I would like this to update itself. Say I close the program and run it again, the counting should start from 2.
My only problem is numbering the lines. Could someone point me in the right direction how to do this, or show me a sample source code?
You could process each character one by one, and increment a counter that you print before the character when you encounter a carriage return (\n).
In pseudo-code:
lineNumber = 1;
Open the file
While ((c = read a character) is not EOF)
If (c is \n)
Print "lineNumber", then increment it
Print c
End while
Close the file
It's too late, but I hope it helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
/* user input */
char text[50];
char res[100] = "";
printf("Enter a short story (<100 characters): ");
char ch;
char *ptr = text;
while ((ch = getchar()) != EOF) {
*ptr++ = ch;
}
printf("\nYou've entered this text:\n");
printf("%s\n", text);
/* append and create a new text */
strcat(res, "0: ");
char *qtr = text;
int i = 1;
while (*qtr != '\0') {
if (*qtr != '\n') {
char temp[2];
sprintf(temp, "%c", *qtr);
strcat(res, temp);
} else {
char temp[5];
sprintf(temp, "\n%d: ", i++);
strcat(res, temp);
}
qtr++;
}
printf("\nLine number added: \n");
printf("%s\n", res);
return 0;
}
Related
C isn't the language I know so I'm out of my comfort zone (learning C) and I have ran into an issue that I can't currently figure out.
I am trying to read from a text file one word at a time and compare it to a word that I have passed into the function as a pointer.
I am currently reading it from the file one character at a time and storing those characters in a new char array until it hits a space, then comparing that char array to the original word stored in the pointer (stored where it's pointing to, anyway).
When I do a printf to check if both arrays are the same they are, they both equal "Hello". At first I thought maybe it's because my char array doesn't have an end terminator but I tried adding one but still nothing is seeming to work.
My code is below and I would appreciate any help. Again C isn't my strong area.
If I do "Hello" it will be > 0 by the way, so I think it's because the gets() stdin function is also including the enter key or something of that sort. I am not sure of a better way to grab the string though.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int partA(char*);
main()
{
// Array to store my string
char myWord[81];
// myword = pointer to my char array to store. 80 = the size (maximum). stdin = standard input from my keyboard.
fgets(myWord, 80, stdin);
partA(myWord);
}
int partA(char *word)
{
// points to file.
FILE *readFile;
fopen_s(&readFile, "readThisFile.txt", "r");
char character;
char newWord[50];
int i = 0;
while ((character = fgetc(readFile)) != EOF)
{
if (character == ' ')
{
newWord[i] = '\0';
int sameWord = strcmp(word, newWord);
printf("Word: %s", word);
printf("newWord: %s", newWord);
if (sameWord == 0)
printf(" These words are the same.");
if (sameWord > 0)
printf(" sameWord > 0.");
if (sameWord < 0)
printf(" sameWord < 0.");
printf("\n");
i = 0;
}
if (character != ' ')
{
newWord[i] = character;
i++;
}
printf("%c", character);
}
fclose(readFile);
return 1;
}
I take user input using fgets() and store it into a temp array. I then concatenate that to a main array called userInput so that the user can enter multiple lines.
Let's say the user enters the following:
This is a sentence
This is a new line
I need it to print each line in the order they were entered but reverse the order of words like below:
sentence a is This
line new a is This
I have the current approach but I get this:
line
new a is sentence
This a is This
Below is my code where I call reversePrint() with a string to reverse:
void printToSpace(const char *str) {
do {
putc(*str, stdout);
} while(*str++ != ' ');
}
void reversePrint(const char *str) {
const char *p = strchr(str, ' ');
if (p == NULL) {
printf("%s", str);
}
else {
reversePrint(p + 1);
printToSpace(str);
}
}
Here is an alternative way:
#include <stdio.h>
#include <string.h>
void reversePrint(const char *str)
{
if (str)
{
reversePrint(strtok (NULL, " \t\n\r"));
printf("%s ", str);
}
}
int main(void)
{
char string[] = "This is a sentence";
reversePrint(strtok(string, " \t\n\r"));
return 0;
}
It seems so clear and simple that I suspect if strtok() is born for requirements like this.
Here are just a few thoughts...
I feel that using fgets will provide you with an undesired new-line marker. Hence, you need to handle the "\r\n" in the reverse printing function.
I feel that the reverse printing is easier to perform in a single function, although I loved the recursive approach, so I'll use it here.
I should point out that I wouldn't use a recursive function if this was a production application, as we'll be wasting resources and bloating the stack for no good reason.
On a non-recursive approach I would probably use the %.*s format, instead of printing each char separately.
I think your code would work if you only changed printToSpace so that it manages the \n contingency - but I felt like re-writinfg the function. Try this in your solution:
void printToSpace(const char *str) {
do {
putc(*str, stdout);
} while(*str && *str != '\n' && *str != '\r' && *str++ != ' ');
}
Here's my full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_rev(char* str);
// collects two strings and send them to the `print_rev` function
int main(int argc, char const* argv[]) {
char str_array[2][255];
// Get string 1
printf("Enter the first string (up to 255 characters):\n");
fgets(str_array[0], 255, stdin);
printf("Please enter the second string (up to 255 characters):\n");
fgets(str_array[1], 255, stdin);
printf("You entered:\n1. %s2. %s", str_array[0], str_array[1]);
printf("\nString 1 reversed: ");
print_rev(str_array[0]);
printf("\nString 2 reversed: ");
print_rev(str_array[1]);
printf("\n");
}
// prints a string in reverse order.
void print_rev(char* str) {
// find the first occurrence of the ` ` (space)
char* p = strchr(str, ' ');
// if a space exists...
if (p) {
// call `print_rev` for whatever's after the space.
print_rev(p + 1);
// print a space
putc(' ', stdout);
}
// print every character until an EOL, space or NULL is encountered
while (*str && *str != ' ' && *str != '\n' && *str != '\r')
putc(*(str++), stdout);
}
#include <stdio.h>
#include <string.h>
#define MAX_LEN 100000
int main()
{
char str[MAX_LEN], temp[MAX_LEN];
printf("Enter the Sentence to print reverse : ");
scanf("%[^\n]%*c", &str);
int i, left, right, length = strlen(str);
left = 0;
right = length - 1;
printf("%d \n", length);
for(i=0;i<length;i++)
{
temp[i] = str[right];
right--;
}
printf("%s",temp);
return 0;
}
Write a program that will read standard input and echo each line to standard output with a line number and tab preceding it. When you run this program and enter lines from the terminal, lines of input will be interspersed with lines of output. If your system has output redirection and you redirect output to a file, the file will look like the input with the lines numbered.
Here is an example of how the script should work.
User input in bold.
Enter your text:
This is line 1.
1 This is line 1.
This is line 2.
2 This is line 2.
This is the last line of input.
3 This is the last line of input.
The last line will end the process.
Here is what I have so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Enter your text: \n");
while (1)
{
int ch = getc(stdin);
fflush(stdout);
if(ch == EOF) break;
putc(ch, stdout);
}
return 0;
}
I have been attempting at this for a few hours now to no luck, any help is appreciated. I basically cant get my script to display the example output. I can get my script to display the stdin as an stdout and thats all. This is a C assignment.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(void){
size_t no = 0;
bool line_top = true;
printf("Enter your text: \n");
while (1) {
int ch = fgetc(stdin);
if(ch == EOF) break;
if(line_top)
printf("%zu ", ++no);
line_top = (ch == '\n');
fputc(ch, stdout);
}
fflush(stdout);
return 0;
}
To properly complete the assignment, you need to understand what is the line. The code you have in place reads and prints data symbol-by-symbol. This is not going to print the numbers requested!
There are two solutions here. First is to switch from reading symbol by symbol to line by line, and than print an ever incrementing counter every time you print a line. Second is leave reading symbol-by-symbol, but print an incremented number every time you've read a new line symbol from the input. A slight challenge here is that you would need a state - that is, once you've seen the new line character, you should remember that fact, but not print the number right away - this might be the last line in the input. Instead, print a number whenever your saved state tells you so, and reset the flag after this.
A separate question is what to do with the empty lines - do they participate in counter increment or not - but this is probably beyond the assignment.
Ok you should only do what the assignment requires. Here's the most straight-forward solution I can think of:
#include <stdio.h>
int main(void)
{
char buf[1024];
int num = 0;
/* read a line as long as we can read (no error / EOF) */
while (fgets(buf, 1024, stdin))
{
/* print line number */
printf("%d\t", ++num);
/* print what we actually read */
fputs(buf, stdout);
}
return 0;
}
Test run:
> ./numlines < numlines.c
1 #include <stdio.h>
2
3 int main(void)
4 {
5 char buf[1024];
6 int num = 0;
7
8 /* read a line as long as we can read (no error / EOF) */
9 while (fgets(buf, 1024, stdin))
10 {
11 /* print line number */
12 printf("%d\t", ++num);
13
14 /* print what we actually read */
15 fputs(buf, stdout);
16 }
17
18 return 0;
19 }
20
Code needs to keep track of the beginning of a line. This can be done by reading a line using fgets() or by looking at individual char.
fgets() is likely faster, but it limits line length to some constant.
fgetc() gets 1 unsigned char at a time (or EOF).
The below follows OP's lead, yet adds the inner while loop.
Not much code needed.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned long long line_number = 0;
int ch;
while ((ch = fgetc(stdin)) != EOF) {
printf("%llu\t", ++line_number);
while (ch != EOF && fputc(ch, stdout) != '\n') {
ch = fgetc(stdin);
}
}
return 0;
}
const int buflen = 1024;
char buffer[buflen];
int count = 0;
while (1)
{
char* line = fgets(buffer, buflen, stdin);
if (line == null)
break;
fprintf(stdout, "%d: %s\n", ++count, line);
}
Here's a c++ solution using getline and cout.
#include <string>
#include <iostream>
using namespace std;
int main()
{
unsigned int i=0;
string s;
cout<<"Enter your text: "<<endl;
while (std::getline(cin,s))
{
cout<<++i<<'\t'<<s<<endl;
}
return 0;
}
Here a c solution:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int exit=0, i=0, newline=1;
printf("Enter your text: \n");
while (!exit)
{
int ch = getc(stdin);
if(newline){
printf("\n%d\t",++i);
newline=0;
}
switch(ch){
case '\n':
newline=1;
printf("\n");
break;
case EOF:
printf("\n");
exit=1;
break;
default:
printf("%c",(char)ch);
break;
}
}
return 0;
}
#include<stdio.h>
int main()
{
char line[1000];
int lineno=0;
while((fgets(line,1000, stdin)) != NULL)
{
lineno++;
printf("%d ",lineno);
fputs(line, stdout);
}
}
It will work as you are expected. It is a simple method to do this. You don't have to put the while(1) and if condition and break the loop.
I'm trying to write a code that asks the user to enter a string and takes of all characters except the alphabetical.
Now i did it myself and it doesn't seem to work properly. I'm new to strings so i'm trying to understand and master strings. I tried to use gdb on mac but i don't have all the functions to understand this.
Could you please help?
What the code must do: User inputs (for example): h**#el(l)o&^w
and the output is hello.
here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100];
int i;
int seen = 0;
printf("Enter String: ");
scanf("%s", string);
for (i=0; string[i]!='\0'; i++)
{
if (((string[i]<='a' || string[i]>'z')&&(string[i]<='A' || string[i]>'Z')) ||string[i]!='\0')
{
seen = 1;
}
else
seen = 0;
}
if (seen==0)
{
printf("%s", string);
}
}
well, your code has a couple of important problems:
you're not checking boundaries when iterating… what if I type in a 101 characters string? and a 4242 characters string?
next problem, is that scanf("%s", …) is considered dangerous, for the same reasons
so basically, what you'd want is to use fgets() instead of scanf().
But why not just get the input character by character, and build a string that has only the chars you want? It's simpler and flexible!
basically:
#include <ctype.h>
int main() {
char* string[100];
int i=0;
printf("Enter your string: ");
do {
// getting a character
char c = getchar();
// if the character is alpha
if (isalpha(c) != 0)
// we place the character to the current position and then increment the index
string[i++] = c;
// otherwise if c is a carriage return
else if (c == '\r') {
c = getchar(); // get rid of \n
// we end the string
string[i] = '\0'
}else if (c == '\n')
// we end the string
string[i] = '\0';
// while c is not a carriage return or i is not out of boundaries
} while (c != '\n' || i < 100);
// if we've got to the boundary, replace last character with end of string
if (i == 100)
string[i] = '\0';
// print out!
printf("Here's your stripped string: %s\n", string);
return 0;
}
I did not run it on my computer because it's getting late, so my apologies in case of mistakes.
Addendum:
wee the program skips my statement and shuts down
that's because your condition is inversed, and remove the \0 condition, as it will always happen with the scanf() that always append \0 to the string to end it. Try exchanging seen = 1 and seen = 0 or try using the following condition:
if ((string[i]>='a' && string[i]<='z')||(string[i]>='A' && string[i]<='Z')))
seen = 1;
else
seen = 0;
or simply, use ctypes's isalpha() function, like in our two examples!
No part(remove the extra characters) to change the string in your code.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *filter(char *string, int (*test)(int)) {
char *from, *to;
for(to = from = string;*from;++from){
if(test(*from))
*to++ = *from;
}
*to = '\0';
return string;
}
int main(){
char string[100];
printf("Enter String: ");
scanf("%99s", string);
printf("%s\n", filter(string, isalpha));
return 0;
}
I wrote a program to remove a certain word (taken as user input) from a file. I read the word, opened the file from which I wanted to delete the word, read each line in the file and split it into words, and compared each word with my keyword. If they are not a match, I printed them into a temporary file.
But when I open the temp file, the entire text has been copied. Can somebody help me????
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
main()
{
int i;
FILE *fp1,*fp2;
char key[1000],a[1000],temp[1000];
printf("\nEnter the word to be deleted from file : ");
scanf("%s",key);
fp1 = fopen("a.txt","r");
fp2 = fopen("b.txt","w");
while(fgets(a,1000,fp1))
{
for(i=0;a[i]!='\0';++i)
if(a[i]==' ')
break;
else
temp[i]=a[i];
temp[i]='\0';
if(strcmp(temp,key)!=0)
{
fputs(temp,fp2);
}
bzero(a,1000);
}
fclose(fp1);
fclose(fp2);
printf("\n\n");
/*remove("a.txt");
rename("b.txt","a.txt");*/
}
Yet another solution. It has some of the same problems mentioned above, for example the boundaries of a word do not really match English grammar. It also has an inefficiency of doing more copies than is strictly necessary in some cases.
However, I prefer this version over yours because it abstracts the word removal task rather than doing it inline with the rest of the code. Plus it works better.
#include <stdio.h>
#include <string.h>
void remove_str2(char* buffer, char* find, int lfind) {
char* paste = strstr(buffer, find);
if (!paste) { return; }
char* start = paste + lfind;
while (1) {
char* end = strstr(start, find);
if (!end) {
end = start + strlen(start) + 1;
}
memmove(paste, start, end - start);
paste += end - start;
start = strstr(end, find);
if (!start) { return; }
start += lfind;
}
}
void remove_str(char* buffer, char* find, int lfind) {
char* p = strstr(buffer, find);
if (p) {
remove_str(p + lfind, find, lfind);
// shift everything left
do { *p = *(p + lfind); } while (*(++p));
}
}
int main() {
FILE *fp1, *fp2;
char key[1000], a[1000];
// require key to be preceeded by a space
key[0] = ' ';
printf("\nEnter the word to be deleted from file : ");
scanf("%s", &key[1]);
fp1 = fopen("a.txt","r");
fp2 = fopen("b.txt","w");
while (fgets(a, 1000, fp1)) {
remove_str(a, key, strlen(key));
fputs(a, fp2);
}
fclose(fp1);
fclose(fp2);
printf("\n\n");
return 0;
}
Tried to compile it and it works almost fine except it doesn't insert spaces in output file ;)
if(strcmp(temp,key)!=0)
{
temp[i++] = ' ';
temp[i] = '\0';
fputs(temp,fp2);
}
Also, its' very sensitive code. It doesn't work if I have a line of words. And it shouldn't work if your test file has a spaces before word and your keyword doesn't.
Some observations,
main()
{
//you will need input index, output index
int in, on; //in: input index, on: output index
FILE *fp1,*fp2;
char key[1000],iray[1000],oray[1000];
char* here; //clarifies the comparison
printf("\nEnter the word to be deleted from file : ");
scanf("%s",key);
printf("key: %s",key); fflush(stdout);
if(!(fp1 = fopen("a.txt","r"))) { printf("open error\n"); exit(1); }
if(!(fp2 = fopen("b.txt","w"))) { printf("open error\n"); exit(2); }
while(fgets(iray,sizeof(iray),fp1))
{
printf("line: %s",iray); fflush(stdout);
for(in=on=0; iray[in]; ++in) //'\0' = 0 = false //please indent
{ //please use braces
//printf("%d: %c\n",in,iray[in]); fflush(stdout);
if(iray[in]==' ')
{
oray[on++] = iray[in];
continue; //break gets you out of loop
}
here = &(iray[in]);
//printf("here: %s\n",here); fflush(stdout);
if( !strcmp(here,key) ) //have word?
{
in+=strlen(key); //skip word
continue;
}
oray[on++] = iray[in];
}
oray[on] = '\0';
printf("line: %s",oray); fflush(stdout);
fputs(oray,fp2);
iray[0]=0; //bzero(iray,1000);
oray[0]=0; //bzero(oray,1000);
}
fclose(fp1);
}
Part of the problem is that as soon as you find a space you process the word, but you don't finish processing the remainder of the line. After the fputs, you go to the top of the loop and read another line. When I compile and run your snippet, it indeed ouputs the first word of each line as long as it's not the selected word.
Also when outputting your words, you don't output any space between them and there is no carriage return at the end of lines. Thus all non-matching words are output back-to-back on one line.
There's a few more issues that the following snippet fixes (there's some remaining problems that I didn't solve-- for example, the last non-matching word on a line is not output if there is no trailing space on the line. You can solve this by looking for '\0' as well as space. I didn't do it because it requires changing the loop structure to not exit when '\0' is seen so you get a chance to test for it):
while(fgets(a,1000,fp1))
{
int j = 0;
for(i=0;a[i]!='\0';++i)
if((a[i]==' '){
temp[j++]='\0';
if(strcmp(temp,key)!=0) {
fprintf (fp2, "%s ", temp);
}
j = 0;
}
else
temp[j++]=a[i];
fprintf (fp2, "\n");
}
EDIT: a complete solution:
this is how your loop should look like:
while(fgets(a,1000,fp1))
{
int j=0;
for(i=0;a[i]!='\0';++i)
{
if(a[i]==' ')
{
temp[j]=0;
if(strcmp(temp,key)!=0)
{
fputs(temp,fp2);
}
j=0;
//this should be after fputs if you want to remove the space after obsolete word.
fputs(" ",fp2);
}
else
temp[j++]=a[i];
}
//last word if there is no space after!
if(strcmp(temp,key)!=0)
{
fputs(temp,fp2);
}
fputs("\n",fp2);
a[0] = 0;
}