counting words with arguments, fgets(), strncmp() - c

i would like to write a code that count how often the argument occurs in the input.
those are the requirements:
It may be assumed
that the lines in the input do not exceed 1024 characters. The string #EOF on the beginning of a line indicates the end of the input. It it not necessary to consider word
boundaries, and overlapping words must be counted as well: with an input of baaaab,
the word aa shall be counted three times. Also, the program must be case sensitive.
i already wrote a code, but i seem to have made some mistakes. Does anyone have an idea?
int main(int argc, char *argv[])
{
char buf[1026]="start";
int count=0;
while (strncmp(buf,"#EOF",4)!=0)
{
fgets(buf, 1025, stdin);
if (strncmp(buf, argv[1], strlen(argv[1]))==0)
{
count++;
}
}
if(argc==1)
printf("Please specify a program argument.");
if(argc>=2)
printf("%d", count);
return 0;
}
this is the program input with the argument let:
Let it be, let it be, let it be, let it be.
Whisper words of wisdom, let it be.
#EOF
and there is no output while it should be 4
this is the program input with argument aa:
aa aaaaa aa
aa aaa
#EOF
and the output is 2 while it should be 9
this is the program input with argument EOF:
De volgende EOF behoort ook tot de invoer: EOF
# Net als deze #EOF. Maar hieronder niet meer.
#EOF
and there is no input while it should be 3
thanks in advance

strncmp() tests for exact equality of the first n characters of each string provided. However, what you want is to count each occurrence, not just if the start of the line matches. For example, if you're looking for "let" in "Let it be, let it be, let it be, let it be.", you're only ever testing "Let" against "let". No match, no count. You never test further down the string.
So what you want to do is to loop over the result of fgets(), like so:
fgets(buf, 1025, stdin);
for (char *p = buf; *p; ++p) {
if (strncmp(p, argv[1], strlen(argv[1])) == 0)
{
count++;
}
}
This will test "let" against "Let", then "et ", then "t i", etc. until you've checked the whole line and counted the matches.
If you were to use strstr() instead of strncmp(), the loop would look like this:
for (char *p = buf; (p = strstr(p, argv[1])); ++p)
{
count++;
}

Your code only counts the first occurrence of the word in each line of input. You need to iterate through each input string to find ALL occurrences. Try something like this:
int main(int argc,char *argv[])
{
char buf[1026] = "start";
int len, matches = 0;
if (argc < 2) {
printf("Please specify a program argument.");
exit(1);
}
len = strlen(argv[1]);
while (strncmp(buf,"#EOF",4) != 0) {
fgets(buf,1025,stdin);
int buflen = strlen(buf);
for (int i = 0; i <= buflen - len; ++i) {
if (strncmp(&buf[i],argv[1],len) == 0)
++matches;
}
}
printf("'%s' found %d times\n",argv[1],matches);
return 0;
}

This is a functional and correct code written based on the answer given by Fred Larson
Big thanks to him.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buf[1026]="start";
int N;
int count=0;
char *p;
if(argc==1)
{
printf("Please specify a program argument.\n");
return(1);
}
N=strlen(argv[1]);
while (strncmp(buf,"#EOF",4)!=0)
{
fgets(buf, 1025, stdin);
for (p = buf;*p;p++)
{
if (strncmp(p, argv[1], N)==0)
{
if (strncmp(buf,"#EOF",4)!=0)
count++;
}
}
}
if(argc>=2)
printf("%d\n", count);
return 0;
}

Related

Any reason why my --help info won't print when it's my argv[1]? Any advice is appreciated

I'm having trouble getting my --help statement to print if the user enters it for argv[1]. Is there any advice that anyone can provide on what I may be doing wrong? I appreciate any help that can be provided.
I have the strcmp function to compare two strings character by character to see if the first argument is --help or something else.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void help_info(char * info);
void numarg_error_message(char * info2);
int strcmp(const char *string, const char *string2);
int main(int argc, char* argv[])
{
char *helping;
char *helping1;
int i, c;
int num_sum = 0;
for (i = 0; i < argc ; i++)
{
printf("%s ", argv[i]);
//c = atoi(argv[i]);
//num_sum += c;
}
if (argc < 2)
{
numarg_error_message(helping1);
}
else if (strcmp(argv[1], "--help") == 0)
{
help_info(helping);
}
else
{
printf("Hi");
}
return 0;
}
void help_info(char* help)
{
printf("Usage: p2\n\n");
printf("p2 --help\n");
printf("\tdisplay thus usage material.\n\n");
printf("p2 <1> [<0> <1> ...]\n");
printf("\t calculate the sum, minimum, maximum and mean of the real\n");
printf("\t number arguments. Non-numeric values will be echoed to\n");
printf("\t stdout, one per line, with the numeric results printed\n");
printf("\t following the non-numeric lines.\n\n");
}
void numarg_error_message(char *errormessage)
{
char *help3;
printf("Error: not enough arguments.\n");
help_info(help3);
}
int strcmp(const char * str1, const char * str2) //comparing two strings
{
const char *cmp1 = str1;
const char *cmp2 = str2;
while (*cmp1 == *cmp2)
{
cmp1++;
cmp2++;
}
return (*cmp1 - *cmp2);
}
The expected output is supposed to be the information in the help_info function when I enter --help as my argv[1]. The output I'm getting is "name of program --help Hi" every time. Any advice is appreciated!
Don't implement your own strcmp; it's undefined behavior and most likely slower than the one implemented by the standard C library.
That being said, the control condition for your while loop inside strcmp is wrong. It doesn't stop on the terminating null character at the end of the string.
To fix that, do this:
while (*cmp1 && *cmp1 == *cmp2)
instead of this:
while (*cmp1 == *cmp2)
To combat the undefined behavior, you can name your function compare_string or something similar (as long as the name doesn't start with str), and then change the use of strcmp to that.

Get the text before and after strstr in C

I need to be able to extract the characters before and after a substring, currently I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char *text = (char *) malloc (10000000);
char *word = argv[1];
int rep;
FILE *f;
if(argc < 2)
{
printf("Usage: GET <website> | ./word_counter <word>\n");
exit(1);
}
fread(text, 100, 10000000, stdin);
const char *tmp = text;
f = fopen("output.txt", "w");
fprintf(f, "%s\n", "REPS");
while(tmp = strstr(tmp, word)){
printf("%.50s\n", tmp);
rep++;
tmp++;
}
printf("Word count: %d\n", rep);
fclose(f);
system("gedit output.txt");
return 0;
}
I made a copy of the original input so I could leave it untouched and get the "before" characters from it.
Using strstr() on tmp (the original input copy) I can find the instances of the word I'm looking for and print the first 50 characters. But knowing this, how can I access the 50 characters BEFORE this instance?
Any help will be appreciated. Thanks!
Apart from the printing question itself, there are a couple of errors in your code. I have corrected most of them; a short list is:
Always test if malloc succeeded.
fread(text, 100, 10000000, ..) reads way too many text. 100 * 10000000 = 1000000000, almost a full gigabyte. You only allocated enough memory for 10 Mb.
You read from a text file and treat this data as a string. Therefore, you must make sure the data ends with a 0, else functions such as printf and strstr will try to continue reading after the end.
Your rep variable starts out uninitialized and therefore you will always see a random number.
Always free memory you allocated.
That said, it is slightly more efficient to use a dedicated function to print out text – if only to not put too much in your main. And since it's a function, you can add as many useful parameters into it as you want; I added before and after variables, so you can vary the number of characters shown.
For added niceness, this function prints a correct number of spaces when the phrase is found before the minimum number of before characters, so the results line up nicely. Also, since printing out characters such as tab and newlines will mess up your output, I replaced them with ?.
There is, admittedly, some repetition in print_range but in this case I went for clarity, rather than brevity.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 10000000
void print_range (char *source_text, int startindex, int before, int after, int phrase_length)
{
int i;
if (before > startindex)
{
for (i=0; i<before-startindex; i++)
printf (" ");
startindex = before;
}
for (i=0; i<before; i++)
{
if (strchr ("\t\r\n", source_text[startindex-before+i]))
printf ("?");
else
printf ("%c", source_text[startindex-before+i]);
}
for (i=0; i<phrase_length; i++)
{
if (strchr ("\t\r\n", source_text[startindex+i]))
printf ("?");
else
printf ("%c", source_text[startindex+i]);
}
for (i=0; i<after; i++)
{
if (!source_text[startindex+phrase_length+i])
break;
if (strchr ("\t\r\n", source_text[startindex+phrase_length+i]))
printf ("?");
else
printf ("%c", source_text[startindex+phrase_length+i]);
}
printf ("\n");
}
int main (int argc, char *argv[]){
char *text = (char *) malloc (MAX_LENGTH);
char *word = argv[1];
int rep = 0;
if (!text)
return -1;
if(argc < 2)
{
printf("Usage: GET <website> | ./word_counter <word>\n");
exit(1);
}
fread(text, 1, MAX_LENGTH, stdin);
text[MAX_LENGTH] = 0;
const char *tmp = text;
do
{
tmp = strstr(tmp, word);
if (!tmp)
break;
print_range (text, tmp-text, 16,16, strlen(word));
rep++;
tmp++;
} while (1);
free (text);
printf ("Word count: %d\n", rep);
return 0;
}
Result of running this on its own source code:
~/Documents $ ./wordcounter printf < wordcounter.c
tindex; i++)????printf (" ");???starti
-before+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
before+i]);??}??printf ("{");??for (i=
rtindex+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
tindex+i]);??}??printf ("}");??for (i=
_length+i]))????printf ("?");???else??
"?");???else????printf ("%c", source_t
length+i]);??}??printf ("\n");?}??int
argc < 2)??{??? printf("Usage: GET <we
?free (text);???printf ("Word count: %
Word count: 12

Selecting lines with length, C filter

I am writing a filter that should select all lines having a specified length. I ended up having this code, but I don't know how to specify n. I mean, n (and optionally m) should be replaced by a number of lines in command prompt, but I have no idea how to describe it in the code. I thought of case "%d", but from what I know it's not possible to write it like that. That's the code I have so far:
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
int n;
int m;
char line[200];
while(fgets(line,sizeof(line)/sizeof(char), stdin)!=NULL)
{
if(argc>1){
switch(argv[0][0])
{
case 'n':
strlen(line)==n;
break;
case '#n':
strlen(line)<n;
break;
case 'n m':
strlen(line)>=n && strlen(line)<=m;
break;
case 'n#':
strlen(line) > n;
break;
}
printf("%s\n", line);
}}
return 0;
}
Your help would mean a lot to me! I don't really know how to make it work anymore.
I think you should parse the command line outside of your loop. Assuming you are going to require the caller of your program to specify both n and m on the command line, it's a simple matter of grabbing the first two parameters and converting them to integers, and then loop over your stdard input. Something like this:
/* call this minmax.c */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
int n, m, len;
char line[200];
if (argc < 3) {
printf("Must specify min & max line length.");
return -1;
}
n = atoi(argv[1]);
m = atoi(argv[2]);
while(fgets(line, 200, stdin) != NULL) {
len = strlen(line);
if (len >=n && len <= m)
printf(line);
}
return 0;
}
Assuming you are running on *nix:
cc -ominmax minmax.c
Then call it with the min and max line lengths
./minmax 2 5
This will echo back every line you type that is at least 2 characters, but no more then 5.
I hope I understand well the aim of your desired program and here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i=1,n,m; // n and m are the variable which holds
// the limited length
if(argc>=3)
{
// you need to execute the program with this form
// program.exe n m <file.txt
n=atoi(argv[1]); // get the value of n
m=atoi(argv[2]); // get the value of m
printf("n=%d m=%d\n",n,m);
}
char line[1000]; // this variable will hold each line of the file
while (fgets(line,sizeof(line),stdin)) // fgets used to read
{ //the lines in file till the newline
int length=strlen(line)-1;
// we decrement the length to get rid of
// the newline character
if (length < n)
{
printf("line %d:%s status: < %d\n",i,line,n);
}
else if (length==n)
{
printf("line %d:%s status: = %d\n",i,line,n);
}
else if (length>n && length <=m)
{
printf("line %d:%s status: %d < <= %d\n",i,line,n,m);
}
else
{
printf("line %d:%s status: > %d\n",i,line,m);
}
i++;
}
return 0;
}
In case the code does not fit to your needs I think it is sufficient and can be taken as a support for your exact program as it encompasses everything you need !! Hope it helps !!

Processing outputs of multiple inputs in C

It's not something trivial but I would like to know the best way to process multiple outputs, for example:
Input
First line of input will contain a number T = number of test cases. Following lines will contain a string each.
Output
For each string, print on a single line, "UNIQUE" - if the characters are all unique, else print "NOT UNIQUE"
Sample Input
3
DELHI
london
#include<iostream>
Sample Output
UNIQUE
NOT UNIQUE
NOT UNIQUE
So how can I accomplish outputs like that? My code so far is:
int main(int argc, char *argv[])
{
int inputs, count=0;
char str[100];
char *ptr;
scanf("%d",&inputs);
while(inputs-- >0)
{
scanf("%s",str);
for(ptr=str; *ptr!='\0';ptr++)
{
if( *ptr== *(ptr+1))
{
count++;
}
}
if(count>0)
{
printf("NOT UNIQUE");
}
else
{
printf("UNIQUE");
}
}
}
But the above will obviously print the output after each input, but I want the output only after entering all the inputs, if the user enters 3, then the user have to give 3 strings and after the output will be given whether the given strings are unique or not. So I want to know how can I achieve the result given in the problem. Also another thing I want to know is, I am using an array of 100 char, which it can hold a string up to 100 characters, but what do I have to do if I want to handle string with no limit? Just declaring char *str is no good, so what to do?
Hope this helps:
#include <stdio.h>
int main(int argc, char *argv[])
{
int inputs,count=0;
char str[20];
scanf("%d",&inputs);
char *ptr;
char *dummy;
while(inputs-- >0)
{
scanf("%s",str);
for(ptr=str; *ptr!='\0';ptr++)
{
for(dummy=ptr+1; *dummy != '\0';dummy++)
{
if( *ptr== *dummy)
{
count=1;
}
}
if(count == 1)
break;
}
if(count>0)
{
printf("NOT UNIQUE");
}
else
{
printf("UNIQUE");
}
}
}
If you want to save stuff for later use, you must store it somewhere. The example below stores up to 10 lines in buf and then points str to the current line:
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* for strlen */
#include <ctype.h> /* for isspace */
int main(int argc, char *argv[])
{
int ninput = 0;
char buf[10][100]; /* storage for 10 strings */
char *str; /* pointer to current string */
int i;
printf("Enter up to 10 strings, blank to and input:\n");
for (i = 0; i < 10; i++) {
int l;
str = buf[i];
/* read line and break on end-of-file (^D) */
if (fgets(str, 100, stdin) == NULL) break;
/* delete trailing newline & spaces */
l = strlen(str);
while (l > 0 && isspace(str[l - 1])) l--;
str[l] = '\0';
/* break loop on empty input */
if (l == 0) break;
ninput++;
}
printf("Your input:\n");
for (i = 0; i < ninput; i++) {
str = buf[i];
printf("[%d] '%s'\n", i + 1, str);
}
return 0;
}
Note the two separate loops for input and output.
I've also rejiggled your input. I'm not very fond of fscanf; I prefer to read input line-wise with fgets and then analyse the line with strtok or sscanf. The advantage over fscanf is that yout strings may contain white-space. The drawback is that you have a newline at the end which you usually don't want and have to "chomp".
If you want to allow for longer strings, you should use dynamic allocation with malloc, although I'm not sure if it is useful when reading user input from the console. Tackle that when you have understood the basics of fixed-size allocation on the stack.
Other people have already pointed you to the error in your check for uniqueness.

Strings in C Language

How can you code this in C language if the output is like this? I need strings format of the code because our topic is strings.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char my_string[50];
printf("Enter a word:");
scanf("%s", my_string);
printf("Enter a word:");
scanf("%s", my_string);
// Some unknown code here...
// this part is my only problem to solve this.
getch();
}
Output:
Hello -> (user input)
World -> (user input)
HWeolrllod -> (result)
Okay, you need to do some investigating. We don't, as a general rule, do people's homework for them since:
it's cheating.
you'll probably get caught out if you copy verbatim.
it won't help you in the long run at all.
The C library call for user input that you should use is fgets, along the line of:
char buffer[100];
fgets (buffer, sizeof(buffer), stdin);
This will input a string into the character array called buffer.
If you do that with two different buffers, you'll have the strings in memory.
Then you need to create pointers to them and walk through the two strings outputting alternating characters. Pointers are not an easy subject but the following pseudo-code may help:
set p1 to address of first character in string s1
set p1 to address of first character in string s1
while contents of p1 are not end of string marker:
output contents of p1
add 1 to p1 (move to next character)
if contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
while contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
Translating that into C will take some work but the algorithm is solid. You just need to be aware that a character pointer can be defined with char *p1;, getting the contents of it is done with *p1 and advancing it is p = p + 1; or p1++;.
Short of writing the code for you (which I'm not going to do), there's probably not much else you need.
void main()
{
char my_string1[50],my_string2[50]; int ptr;
ptr=0;
printf("Enter a word : ");
scanf("%s",my_string1);
printf("enter a word");
scanf("%s",my_string2);
while(my_string1[ptr]!='\0' && my_string2[ptr]!='\0')
{
printf("%c%c",my_string1[ptr],my_string2[ptr]);
ptr++;
}
if(my_string1[ptr]!='\0')
{
while(my_string1[ptr]!='\0')
{ printf("%c",my_string1[ptr]);
ptr++;
}
}
else
{
while(my_string2[ptr]!='\0')
{printf("%c",my_string2[ptr]);
ptr++;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char my_string1[50],my_string2[50];
int i,l1=1,l2=0;
printf("Enter a word:");
scanf("%s", my_string1);
printf("Enter a word:");
scanf("%s", my_string2);
l1=strlen(my_string1); /* Length of 1st string */
l2=strlen(my_string2); /* Length of 2nd string */
if(l1==l2)
{
for(i=0;i<l1;i++)
{
printf("%c%c",my_string1[i],my_string2[i]);
}
}
else
{
printf("Length of the entered strings do not match");
}
}
This is your required code.
You can see that output needs to be a String containing all chars of User String1 and User String2 one by one...
You can do this like...
//add #include<String.h>
int l1=strlen(s1);
int l2=strlen(s2);
if(l1!=l2)
{
printf("length do not match");
return 0;
}
char ansstr[l1+l2];
int i,j=0,k=0;
for(i=0;i<l1+l2;i=i+2)
{
ansstr[i]=s1[j];
ansstr[i+1]=s2[k];
j++;
k++;``
}
//ansstr is your answer
Ok, here's your code. Come on guys, if he asked here it means he can't solve this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char str1[] = "abcdefghijklmopq";
char str2[] = "jklm";
int len1 = strlen(str1);
int len2 = strlen(str2);
int c1 = 0, c2 = 0;
int max = (len1 > len2) ? len1 : len2 ;
char *result = malloc(len1 + len2);
for(c1 = 0; c1 <= max; c1++) {
if(c1 < len1)
result[c2++] = str1[c1];
if(c1 < len2)
result[c2++] = str2[c1];
}
result[c2] = 0;
printf("\n%s\n", result);
return 0;
}
Basically the loop picks up a character from str1 and appends it to result. Then it picks a character, which stands in the same position as the first from str2 and appends it to result, just as before. I increment c2 by 2 every time because I'm adding 2 chars to result. I check if c1 is bigger that the length of the strings because I want to copy only the characters in the string without the terminating \0. If you know that your strings have the same length you can omit these ifs.

Resources