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");
}
}
}
Related
My program needs to print longest word which contains only letters from a file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int checkString(const char s[]) {
unsigned char c;
while ((c = *s) && (isalpha(c) || isblank(c)))
++s;
return *s == '\0';
}
int main() {
char file_name[]="document.txt";
FILE *fp = fopen(file_name, "r");
char *largest = str;
int largest_len = 0;
while (fgets(file_name, 1000, fp) != NULL) {
char *temp = strtok(file_name, " ");
while (temp != NULL) {
if (strlen(temp) > largest_len) {
strcpy(largest, temp);
largest_len = strlen(largest);
}
temp = strtok(NULL, "\",.,1,2,4,5,6,7,8,9 ");
}
}
if(checkString(largest))
printf("%s", largest);
fclose(fp);
return 0;
}
In my code, if the largest word contains only letters it will be printed. How to modify this code to check next words if the largest doesn't contain only letters?
First of all, you cannot store the pointer to longest word like that. You re-use str for the next line and so the pointer is not likely to point to something useful.
Second, while strtok() appears simple, initially, I tend to apply a straightforward approach to a straightforward problem.
The problem is O(n) (where n is the length of the document). You just need to go through it character by character. Of course, since every line is ended by a \n, you can use the line based approach in this case.
So, instead of strtok, simply check each character, if it is a legal word character (an alphanumeric character, that is). You can easily do so with the standard library function isalpha() from header ctype.h.
Below is the program, copying the longest string into a dedicated buffer, using isalpha() and doing the line based reading of the file, just like the code in the original question did.
Of course, this code assumes, no line is ever longer than 999 characters.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
static size_t gulp(const char* line, size_t istart, size_t len) {
size_t n = 0;
for (size_t i = istart; i < len; i++, n++) {
if (!isalpha(line[i])) {
break;
}
}
return n;
}
int main(int argc, const char * argv[]) {
FILE* f = fopen("document.txt","r");
char line[1000];
char longest_word[1000];
size_t longest_word_length = 0;
while (fgets(line, sizeof(line), f) != NULL) {
size_t i0 = 0;
size_t line_length = strlen(line);
while (i0 < line_length) {
if (isalpha(line[i0])) {
size_t n = gulp(line, i0, line_length);
if (n > longest_word_length) {
strncpy(longest_word, &line[i0], n);
longest_word[n] = '\0';
longest_word_length = n;
}
i0 = i0 + n;
} else {
i0++;
}
}
}
fclose(f);
f = NULL;
if (longest_word_length > 0) {
printf("longest word: %s (%lu characters)\n",
longest_word, longest_word_length);
}
return 0;
}
There are a number of problems here:
you use the same buffer (str) for two different uses: as a read buffer and to store the longest word. If you find the largest word in the first line, the word will be erased when reading the second line. Furthemore, if you find a rather long word at the beginning of a line, the strings pointed to by largest and temp could overlap which leads to undefined behaviour => use a different array or strdup (and free) for largest
you only use the space as possible separator. You should wonder whether you should add tab and/or punctuations
once you have got a word you should ensure that it only contains valid letters before testing its length and ignore it if for example it contains digits.
if a single line can be longer than 1000 characters, you should wrap the end of the current part before the beginning of the next one for the possible case where a long word would be splitted there.
For additional corner case processing, you should specify what to do if a word contains illegal characters but only at one side. For example if . is not used as a word delimiter, a word with an embedded . like "a.b" should be ignored, but a terminating . should only be stripped (like "example." should become "example"
I think the order you do things should be a bit different, here is an example
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int isCandidate(char* word);
int main(int argc, char* argv[])
{
if (--argc == 0)
{
perror("not enough command line arguments, expecting a filename");
return -1;
}
++argv;
FILE* fp = fopen(*argv, "r");
if (fp == NULL)
{
perror(*argv);
return -1;
}
// get size of file
fseek(fp, 0L, SEEK_END);
long fileLength = ftell(fp);
if (fileLength < 1)
{
perror("file is empty");
return -1;
}
fseek(fp, 0L, SEEK_SET); // position file pointer at the beginning again
// allocate space for the whole file and then read it in
// for a text file it should be OK to do so since they
// normally are not that large.
char* buffer = malloc(fileLength+1);
if (fread(buffer, 1, fileLength, fp) != 0)
{
buffer[fileLength] = '\0'; // make sure the buffer ends with \0
}
else
{
perror("Failed reading into buffer");
return -1;
}
fclose(fp); // we are done with the file
const char filter[] = " \n\r";
char* longestWord = malloc(fileLength+1); // max length in theory
long unsigned int maxLength = 0;
for (char* token = strtok(buffer, filter); token != NULL; token = strtok(NULL, filter))
{
if (isCandidate(token))
{
if (strlen(token) > maxLength)
{
strcpy(longestWord, token);
maxLength = strlen(token);
}
}
}
printf("Longest word:'%s', len=%lu\n", longestWord, maxLength);
free(longestWord);
free(buffer);
}
int isCandidate(char* word)
{
if (word == NULL)
{
perror("invalid argument to isCandidate");
return 0;
}
for (char* ch = word; *ch; ++ch)
{
if (!isalpha(*ch)) return 0;
}
return 1;
}
I have a csv file of double values ( 20 rows and 4 columns) that I want to read and store the values in a buffer to perform some operations. My following implementation gives me some characters on the screen. I tried to see where is the problem but I don't know where:
#include<stdio.h>
#include <stdlib.h>
#include<String.h>
int main()
{
char buff[80];
double buffer[80];
char *token = NULL;
FILE *fp = fopen("dataset.csv","r");
if(fp == NULL){
printf("File Reading ERROR!");
exit(0);
}
int c = 0;
do
{
fgets(buff, 80, fp);
token = strtok(buff,",");
while( token != NULL )
{
buffer[c] = (char) token;
token = strtok(NULL,",");
c++;
}
}while((getc(fp))!=EOF);
for(int i=1; i<=80; ++i){
printf("%c ", buff[i]);
if(i%4 == 0) printf("\n");
}
}
Any help is appreciated.
Nice attempt, modify it a bit, like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // not String.h
int main(void)
{
char buff[80];
double buffer[80] = {0}; // I like initialization my arrays. Could do for 'buff' too
char *token = NULL;
FILE *fp = fopen("dataset.csv","r");
if(fp == NULL){
printf("File Reading ERROR!");
exit(0);
}
int c = 0;
while(fgets(buff, 80, fp) != NULL) // do not use 'getc()' to control the loop, use 'fgets()'
{
// eat the trailing newline
buff[strlen(buff) - 1] = '\0';
token = strtok(buff, ",");
while( token != NULL )
{
// use 'atof()' to parse from string to double
buffer[c] = atof(token);
token = strtok(NULL,",");
c++;
}
}
// print as many numbers as you read, i.e. 'c' - 1
for(int i=1; i<=c - 1; ++i) // be consistent on where you place opening brackets!
{
printf("%f\n", buffer[i]);
}
// Usually, we return something at the end of main()
return 0;
}
Sample run:
C02QT2UBFVH6-lm:~ gsamaras$ cat dataset.csv
3.13,3.14,3.15,3.16
2.13,2.14,2.15,2.16
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
3.140000
3.150000
3.160000
2.130000
2.140000
2.150000
2.160000
Notes:
Use atof() to
parse from string to double in c.
We usually prefer fgets() over
getc().
You are typecasting token to (char). token is a character pointer - basically, a pointer to the string containing the next ,-delimited token. You need to parse the floating point number contained within that string to a double value, not typecast the string pointer itself to a char value. Try sscanf() for this.
When you output your values, you are outputting characters from the last input buffer, not the double values that you (attempt to) parse out of the input. Change your printf command to output double values (e.g. %f or %g) and pass it the values out of your buffer array of doubles, not the buff character array.
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.
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;
}
I'm new to C, and I'm trying to scan a line from stdin and extract the nth word from it.
Right now I've hard-coded it where you can store the first, second, or third entry in the sentence, and this is what it looks like:
int set_to_nth_word(char* word, char* input, int n)
{
char word1[20];
char word2[20];
char word3[20];
if(sscanf(input, "%s %s %s", word1, word2, word3) < n)
{
printf("You didn't enter enough values\n");
return 0;
}
else
{
if(n == 1) strcpy(word, word1);
else if(n == 2) strcpy(word, word2);
else if(n == 3) strcpy(word, word3);
return 1;
}
}
The code that calls this method is:
char *input = (char *) malloc (1);
if(getline(&input, (size_t)0, stdin) != -1)
{
char word[20];
if(set_to_nth_word(word, input, 1))
{
printf("Success");
}
}
Besides finding a solution to this problem, I'd be happy if anyone points out any bad style or bad coding practices!
You can make use of %n conversion specifier supported by sscanf(). It requires an int * parameter, and returns the number of characters consumed from the input into that int.
int set_to_nth_word(char *word, const char *input, int n)
{
int chars_used;
word[0] = '\0'; /* In case n < 1 */
while (n > 0 && sscanf(input, "%s%n", word, &chars_used) > 0)
{
input += chars_used;
n--;
}
if (n > 0)
{
printf("You didn't enter enough values\n");
return 0;
}
return 1;
}
As far as style goes, you should make the input parameter const char *, since the characters pointed to are not being modified in the function.
In terms of safety, word should be allocated with a length of strlen(input) + 1, rather than declared as a fixed-size array, since the words may be up to that length.
Here are a few pieces of advice:
instead of scanning a fixed number of words, loop n times scanning a single word
use strtok instead of sscanf for this; it will make your life much easier
try to avoid compiled-in limits on how long a word can be (20), especially when you're not checking to see if those limits are being exceeded
avoid copying string data unnecessarily when scanning it, especially (as stated above) when you're not enforcing length limits on your strcpy calls. Using strtok will locate words within the input with zero copies.
Homework? As homework assignments go, it's a bit interesting, as it tempts one to implement a crude and limited solution yet allows a fairly easy true solution.
Anyway, here is my shot at it...
#include <stdio.h>
#include <stdlib.h>
int set_to_nth_word(char *word, const char *input, int n) {
int i;
size_t used = 0;
char convert[1000];
static const char convertPattern[] = " %*s";
static const char convertReal[] = " %s";
if((unsigned)n > sizeof convert / sizeof convertPattern - 1)
return 0;
for(i = 1; i < n; ++i)
used += sprintf(convert + used, "%s", convertPattern);
sprintf(convert + used, "%s", convertReal);
return sscanf(input, convert, word) == 1;
}
int main(int ac, char **av) {
static char space[1000];
static char wordn[1000];
if (ac > 1) {
fgets(space, sizeof space, stdin);
if(set_to_nth_word(wordn, space, atoi(av[1])))
printf("%s\n", wordn);
}
return 0;
}