Operations with text and delimiters - c

The task is: to read the text from file and to read an array of delimiters from keyboard. Than the program should search the sequence of delimiters in the text and, if it would be found 3 times or more, swap all the odd strings in a circle. Also it should detete all the words, which exceed the length limit, entered by user, but only in odd strings.
This is what i've got now:
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
int main(void)
{
setlocale(LC_ALL, "Russian"); //entering the text
const int numberOfCharactersToRead = 128;
char* inputText = (char*)(malloc(sizeof(char) * numberOfCharactersToRead));
FILE *fp;
fopen_s(&fp, "D:\texxxt.txt", "r");
if (fp == NULL)
{
printf("nFile not foundn");
system("pause");
return 0;
}
fgets(inputText, numberOfCharactersToRead, fp);
printf("Enter the sequence of delimiters: "); //entering delimiters
const int numberOfDelimitersToRead = 6;
char* delimiters = (char*)(malloc(sizeof(char) * numberOfDelimitersToRead));
int indexer = 0;
for (indexer = 0; indexer < numberOfDelimitersToRead; indexer++)
{
delimiters[indexer] = getchar();
}
//Trying to use strtok in order to devide text into rows (unsuccesful)
char delims[] = "/n";
char *pch = strtok_s(NULL, inputText, &delims);
printf("nLexems:");
while (pch != NULL)
{
printf("n%s", pch);
pch = strtok_s(NULL, inputText, &delims);
}
return 0;
}
int symcount(void)
{ //function searching the quantity of delimiters
char str[20], ch;
int count = 0, i;
printf("nEnter a string : ");
scanf_s("%s", &str);
printf("nEnter the character to be searched : ");
scanf_s("%c", &ch);
for (i = 0; str[i] != ''; i++)
{
if (str[i] == ch)
count++;
}
if (count == 0)
printf("nCharacter '%c'is not present", ch);
else
printf("nOccurence of character '%c' : %d", ch, count);
return (0);
}
I dont really know how to devide the text into rows and how to make my program differentiate even and odd strings. I'm really confused

The definition of strtok_s is the following:
char *strtok_s(char *strToken, const char *strDelimit, char **context);
You are mixing up the parameters. The 1st parameter should be a pointer to the input string and the 2nd parameter should be the delimiter string. Finally after the function is executed the 3rd parameter will be passed a pointer to the string after the position where the delimiter was found, or NULL if no delimiter was found. This pointer can then be passed onto the next strtok_s call to continue the search.
char *pchNext;
char *pch = strtok_s(inputText, delimiters, &pchNext);
while (pch != NULL)
{
printf("\n%s", pch);
pch = strtok_s(NULL, delimiters, &pchNext); // The first parameter can be NULL here
}
Also, the textual representation of the newline character is \n, not /n or n.

Related

count the occurrences of each word in that phrase using C language

I am not understanding why, when I am doing sub=strtok(NULL,delim);, instead of going to the next word, it is making it null. Please try this code and help me resolve the problem.
#include <stdio.h>
#include <string.h>
int main()
{
char str[100],str1[100],*sub,*sub1;
int c1;
printf("\nEnter the string or sentence: ");
scanf("%[^\n]%*c",str);
strcpy(str1,str);
char delim[]=" ";
sub=strtok(str,delim);
while(sub !=NULL)
{
c1=0;
sub1=strtok(str1,delim);
while(sub1 !=NULL)
{
if(!strcmp(sub,sub1))
{
c1++;
}
sub1=strtok(NULL,delim);
}
printf("\n%s : %d",sub,c1);
sub=strtok(NULL,delim);
}
return 0;
}
You can't parse multiple string buffers concurrently with strtok(), like you are trying to do. Internally, strtok() maintains a static reference to the input string, that is how it knows which string to advance through when subsequent calls specify a NULL string pointer.
Before entering your outer loop, you call strtok(str) to set the internal reference to str. Then, inside the loop, you call strtok(str1) to reset that reference to str1. So, on the 1st iteration of your outer loop, before entering the inner loop, strtok() has already lost its reference to your str buffer since you replace it with the str1 buffer. Then, after the inner loop has finished scanning str1, your outer loop breaks when calling sub=strtok(NULL,delim); because there are no more tokens to read from str1.
For what you are attempting, use strtok_r() instead:
The strtok_r() function is a reentrant version strtok(). The saveptr argument is a pointer to a char * variable that is used internally by strtok_r() in order to maintain context between successive calls that parse the same string.
...
Different strings may be parsed concurrently using sequences of calls to strtok_r() that specify different saveptr arguments.
Also, because strtok(_r)() is destructive to the input string, inserting '\0' after each token found, you need to reset the contents of your 2nd string buffer back to the original string before entering the inner loop. Otherwise, the inner loop will stop scanning after is reads the 1st word in your 2nd string buffer.
Try something more like this:
#include <stdio.h>
#include <string.h>
int main()
{
char orig[100], str1[100], str2[100], *sub1, *sub2, *save1, *save2;
char delim[] = " ";
int c1;
printf("\nEnter the string or sentence: ");
scanf("%[^\n]%*c", orig);
strcpy(str1, orig);
sub1 = strtok_r(str1, delim, &save1);
while (sub1 != NULL)
{
c1 = 0;
strcpy(str2, orig);
sub2 = strtok_r(str2, delim, &save2);
while (sub2 != NULL)
{
if (strcmp(sub1, sub2) == 0)
{
++c1;
}
sub2 = strtok_r(NULL, delim, &save2);
}
printf("\n%s : %d", sub1, c1);
sub1 = strtok_r(NULL, delim, &save1);
}
return 0;
}
Otherwise, you can use a single loop through a single string buffer, storing the word counts in a separate array, eg:
#include <stdio.h>
#include <string.h>
typedef struct _wordInfo
{
char* str;
int count;
} wordInfo;
int main()
{
char str[100], *sub;
char delim[] = " ";
wordInfo words[100], *word;
int numWords = 0;
printf("\nEnter the string or sentence: ");
scanf("%[^\n]%*c", str);
sub = strtok(str, delim);
while (sub != NULL)
{
word = NULL;
for (int i = 0; i < numWords; ++i)
{
if (strcmp(sub, words[i].str) == 0)
{
word = &words[i];
break;
}
}
if (!word)
{
if (numWords == 100) break;
word = &words[numWords++];
word->str = sub;
word->count = 1;
}
else {
word->count++;
}
sub = strtok(NULL, delim);
}
for(int i = 0; i < numWords; ++i)
{
word = &words[i];
printf("\n%s : %d", word->str, word->count);
}
return 0;
}

Searching an array for a specific character [duplicate]

I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what I have done so far:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
Although the output is what I want, I have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end.
I can understand that there is a mistake at my malloc() implementation, but I do not know what it is.
Is there another more elegant or generally better way to do it?
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.
From the website:
char * strtok ( char * str, const char * delimiters );
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.
Parameters
str
C string to truncate.
Notice that this string is modified by being broken into smaller strings (tokens).
Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiter characters.
These may vary from one call to another.
Return Value
A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
For the fun of it here's an implementation based on the callback approach:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
malloc(0) may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?
Consider using strtok_r, as others have suggested, or something like:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
Something going wrong is get_words() always returning one less than the actual word count, so eventually you attempt to:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc() isn't returning a valid ptr, though, I don't know.
You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.
Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
you can scan the char array looking for the token if you found it just print new line else print the char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}

Find Nth Word given a file of Strings and ints C

I need to find the Nth word in a string which is given through standard input through redirection operators in Unix.
Input is something along these lines:
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born
5
The European languages are members of the same family.
3
Can anyone give me any idea as to how to read in the string into a char array and then get the int and use it to find the given word? I've been at it for a while and can't get it to work properly.
#define INPUT_LENGTH 400
int main(void)
{
char input[INPUT_LENGTH];
char integer[INPUT_LENGTH];
int spaces = 0;
int value;
char n;
while(fgets(input, INPUT_LENGTH, stdin)) //read in string line
{
while(fgets(integer, INPUT_LENGTH,stdin)) //read in int
{
int num = sscanf(integer, "%d", &value); //assign int val to num
while(1 == sscanf(input, "%c", &n)) //go through string one char at a time
if(spaces == num && !isspace(n))
printf("%c", n); //print chars if we've reached the word
else if(isspace(n))
spaces++;
}
}
}
I've redone most of it with the comments in mind but still can't seem to have it actually reading in the input through the operator unfortunately.
I'm not certain but I don't think my fgets are correct. I'm rather new to C and am not entirely certain how they process the data even after research
Use strtok like this
#include <stdio.h>
#include <string.h>
#define INPUT_LENGTH 400
int main(void){
char input[INPUT_LENGTH];
char integer[INPUT_LENGTH];
int value;
while(fgets(input, sizeof input, stdin)) //read in string line
{
if(fgets(integer, sizeof integer, stdin)) //read in int
{
if(1==sscanf(integer, "%d", &value)) //assign int value to value
{
char *word = strtok(input, " \t\n");
int n;
for(n = 1; word != NULL && n < value; ++n){// 1 origin
word = strtok(NULL, " \t\n");
}
if(word != NULL && n == value)
puts(word);//Nth word
else
puts("No word");
}
else {
printf("Numerical value is not specified.\n");
}
}
else {
printf("There is no numeric specification line.\n");
}
}
}

read 1/2/5 string inputs in c

i need to read input from the standart input line by line
but each line will contain 1 or 2 or 5 strings like :
bofob fbo
blabla bibi bobo fbo fbooo
bobobo bobo
bobof
how can i do this?
my idea is really not looking profassional and not working
char a[50],b[50],c[50],d[50],f[50];
int numOfStrings=0;
scanf(" %s",a); char a[50],b[50],c[50],d[50],f[50];
int numOfStrings=0;
scanf(" %s",a);
if (scanf (" %s",b)){
numOfStrings=2;
if (scanf (" %s %d %d",c,d,f)
numOfStrings=5;
}
if (scanf (" %s",b)){
numOfStrings=2;
if (scanf (" %s %d %d",c,d,f)
numOfStrings=5;
}
but its not working because it goes and read inputs from the next line
is there a way to read a whole line (i know its max 250 chars) and then know how many words are in there?
edit:
i will add a count words function
but what is the nicest wat ro read a line untilll the end line or eof??
int words(const char *sentence)
{
int count,i,len;
char lastC;
len=strlen(sentence);
if(len > 0)
{
lastC = sentence[0];
}
for(i=0; i<=len; i++)
{
if(sentence[i]==' ' && lastC != ' ')
{
count++;
}
lastC = int words(const char *sentence)
}
return count;
}
You need to use fgets() to take the input line-by-line. check the man page here. It will also liberate you from handling the limitation of [1/2/5/.....] numbers of space-seperated strings. Provided sufficient storage, you can read 1 to any number of "string"s.
Note: You might need to take care of the trailing newline \n [caused by ENTER] yourself. Causes trouble most of the times.
You could scan one line until the '\n' with %[^\n], then split the line into words with strtok():
#include <string.h>
#include <stdio.h>
const char s[2] = " ";
const int MAX_LINE_SIZE = 128;
FILE *fp;
char *word, *str;
int word_counter;
/* Open the file here */
while (fgets(str, MAX_LINE_SIZE, fp) != NULL)
{
word_counter = 0
/* get the first word */
word = strtok(str, s);
/* walk through other words */
while (word != NULL)
{
printf(" %s\n", word);
word_counter++;
word = strtok(NULL, s);
}
printf("This string contains %d words\n",word_counter);
}
/* END of FILE */
You can use fgets to read a file and strchr to count the number of spaces:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[250];
char *p;
FILE *f;
int i;
f = fopen("demo.txt", "r");
while ((p = fgets(s, sizeof s, f))) {
i = 0;
while ((p = strchr(p, ' '))) {
p++;
i++;
}
printf("%d spaces\n", i);
}
fclose(f);
return 0;
}

Split string in C every white space

I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what I have done so far:
void manipulate(char *buffer);
int get_words(char *buffer);
int main(){
char buff[100];
printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff)); // Debugging reasons
bzero(buff, sizeof(buff));
printf("Give me the text:\n");
fgets(buff, sizeof(buff), stdin);
manipulate(buff);
return 0;
}
int get_words(char *buffer){ // Function that gets the word count, by counting the spaces.
int count;
int wordcount = 0;
char ch;
for (count = 0; count < strlen(buffer); count ++){
ch = buffer[count];
if((isblank(ch)) || (buffer[count] == '\0')){ // if the character is blank, or null byte add 1 to the wordcounter
wordcount += 1;
}
}
printf("%d\n\n", wordcount);
return wordcount;
}
void manipulate(char *buffer){
int words = get_words(buffer);
char *newbuff[words];
char *ptr;
int count = 0;
int count2 = 0;
char ch = '\n';
ptr = buffer;
bzero(newbuff, sizeof(newbuff));
for (count = 0; count < 100; count ++){
ch = buffer[count];
if (isblank(ch) || buffer[count] == '\0'){
buffer[count] = '\0';
if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) {
printf("MALLOC ERROR!\n");
exit(-1);
}
strcpy(newbuff[count2], ptr);
printf("\n%s\n",newbuff[count2]);
ptr = &buffer[count + 1];
count2 ++;
}
}
}
Although the output is what I want, I have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end.
I can understand that there is a mistake at my malloc() implementation, but I do not know what it is.
Is there another more elegant or generally better way to do it?
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.
From the website:
char * strtok ( char * str, const char * delimiters );
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.
Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.
Parameters
str
C string to truncate.
Notice that this string is modified by being broken into smaller strings (tokens).
Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiter characters.
These may vary from one call to another.
Return Value
A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.
Example
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
For the fun of it here's an implementation based on the callback approach:
const char* find(const char* s,
const char* e,
int (*pred)(char))
{
while( s != e && !pred(*s) ) ++s;
return s;
}
void split_on_ws(const char* s,
const char* e,
void (*callback)(const char*, const char*))
{
const char* p = s;
while( s != e ) {
s = find(s, e, isspace);
callback(p, s);
p = s = find(s, e, isnotspace);
}
}
void handle_word(const char* s, const char* e)
{
// handle the word that starts at s and ends at e
}
int main()
{
split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
malloc(0) may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?
Consider using strtok_r, as others have suggested, or something like:
void printWords(const char *string) {
// Make a local copy of the string that we can manipulate.
char * const copy = strdup(string);
char *space = copy;
// Find the next space in the string, and replace it with a newline.
while (space = strchr(space,' ')) *space = '\n';
// There are no more spaces in the string; print out our modified copy.
printf("%s\n", copy);
// Free our local copy
free(copy);
}
Something going wrong is get_words() always returning one less than the actual word count, so eventually you attempt to:
char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */
newbuff[count2] = (char *)malloc(strlen(buffer))
count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc() isn't returning a valid ptr, though, I don't know.
You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.
Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.
int print_words(const char *string, FILE *f)
{
static const char space_characters[] = " \t";
const char *next_space;
// Find the next space in the string
//
while ((next_space = strpbrk(string, space_characters)))
{
const char *p;
// If there are non-space characters between what we found
// and what we started from, print them.
//
if (next_space != string)
{
for (p=string; p<next_space; p++)
{
if(fputc(*p, f) == EOF)
{
return -1;
}
}
// Print a newline
//
if (fputc('\n', f) == EOF)
{
return -1;
}
}
// Advance next_space until we hit a non-space character
//
while (*next_space && strchr(space_characters, *next_space))
{
next_space++;
}
// Advance the string
//
string = next_space;
}
// Handle the case where there are no spaces left in the string
//
if (*string)
{
if (fprintf(f, "%s\n", string) < 0)
{
return -1;
}
}
return 0;
}
you can scan the char array looking for the token if you found it just print new line else print the char.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
int len = strlen(s);
char delim =' ';
for(int i = 0; i < len; i++) {
if(s[i] == delim) {
printf("\n");
}
else {
printf("%c", s[i]);
}
}
free(s);
return 0;
}
char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);
for(i=0;i<l;i++){
if(arr[i]==32){
printf("\n");
}
else
printf("%c",arr[i]);
}

Resources