I have the following:
unsigned char input[];
unsigned char *text = &input[];
I'm taking in user input as follows:
do {
printf ("Please enter an numeric message terminated by -1:\n");
fgets(input, sizeof(input), stdin);
}
while (input[0] == '\n')
Since my output will give me an array of individual characters, how
can I go about concatenating them. If I enter input such as:
14 156 23 72 122
when I try to work with it, it's breaking it into:
1 4 1 5 6 ...
In other words, when I want to pass it to a function as an unsigned char,
I want to pass '14', so the function can read the binary of 14, rather than
1, then 4, etc. Any help would be greatly appreciated!
As it stands now, your code does not compile.
You cannot declare these variables like this:
unsigned char input[];
unsigned char *text = &input[];
You need to say how big input is supposed to be. I'm not sure what you're doing with your second definition.
You also need to put a semicolon after this line
while (input[0] == '\n')
All of that aside, if the input is separated by a know delimiter, you could use strtok() instead of reading the string byte by byte.
I scrapped your program because it didn't compile. This is what I assume you're trying to do with your code, adjust accordingly:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
* Converts "input" separated by "delims" to an array of "numbers"
*/
size_t str_to_nums(const char* input, const char* delims, int* numbers, size_t numsize)
{
char* parsed = malloc(strlen(input) + 1); /* allocate memory for a string to tokenize */
char* tok; /* the current token */
size_t curr; /* the current index in the numbers array */
strcpy(parsed, input); /* copy the string so we don't modify the original */
curr = 0;
tok = strtok(parsed, delims);
while(tok != NULL && curr < numsize) { /* tokenize until NULL or we exceed the buffer size */
numbers[curr++] = atoi(tok); /* convert token to integer */
tok = strtok(NULL, delims); /* get the next token */
}
free(parsed);
return curr; /* return the number of tokens parsed */
}
int main(void)
{
char input[256];
int numbers[64];
size_t count, i;
puts("Please enter an numeric message terminated by -1:");
fgets(input, sizeof(input), stdin);
count = str_to_nums(input, " ", numbers, sizeof(numbers)/sizeof(*numbers)); /* string is separated by space */
for(i = 0; i < count; ++i) {
printf("%d\n", numbers[i]); /* show the results */
}
}
P.s. This is not concatenation. The phrase your looking for is "string splitting" or "tokenizing".
Try this!
#include <string.h>
#include <stdio.h>
int main()
{
char *line;
char *token;
scanf(" %[^\n]s",line);
/* get the first token */
token = strtok(line, " ");
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, " ");
}
return(0);
}
Related
I'm trying to make a program that scans a file containing words line by line and removes words that are spelled the same if you read them backwards (palindromes)
This is the program.c file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
int main(int argc, char **argv)
{
if(argc != 3)
{
printf("Wrong parameters");
return 0;
}
FILE *data;
FILE *result;
char *StringFromFile = (char*)malloc(255);
char *word = (char*)malloc(255);
const char *dat = argv[1];
const char *res = argv[2];
data = fopen(dat, "r");
result =fopen(res, "w");
while(fgets(StringFromFile, 255, data))
{
function1(StringFromFile, word);
fputs(StringFromFile, result);
}
free(StringFromFile);
free (word);
fclose(data);
fclose(result);
return 0;
}
This is the header.h file:
#ifndef HEADER_H_INCLUDEC
#define HEADER_H_INCLUDED
void function1(char *StringFromFile, char *word);
void moving(char *StringFromFile, int *index, int StringLength, int WordLength);
#endif
This is the function file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
void function1(char *StringFromFile, char *word)
{
int StringLength = strlen(StringFromFile);
int WordLength;
int i;
int p;
int k;
int t;
int m;
int match;
for(i = 0; i < StringLength; i++)
{ k=0;
t=0;
m=i;
if (StringFromFile[i] != ' ')
{ while (StringFromFile[i] != ' ')
{
word[k]=StringFromFile[i];
k=k+1;
i=i+1;
}
//printf("%s\n", word);
WordLength = strlen(word)-1;
p = WordLength-1;
match=0;
while (t <= p)
{
if (word[t] == word[p])
{
match=match+1;
}
t=t+1;
p=p-1;
}
if ((match*2) >= (WordLength))
{
moving(StringFromFile, &m, StringLength, WordLength);
}
}
}
}
void moving(char *StringFromFile, int *index, int StringLength, int WordLength)
{ int i;
int q=WordLength-1;
for(i = *index; i < StringLength; i++)
{
StringFromFile[i-1] = StringFromFile[i+q];
}
*(index) = *(index)-1;
}
It doesn't read each word correctly, though.
This is the data file:
abcba rttt plllp
aaaaaaaaaaaa
ababa
abbbba
kede
These are the separate words the program reads:
abcba
rttta
plllp
aaaaaaaaaaaa
ababa
abbbba
kede
This is the result file:
abcba rtttp
kede
It works fine if there is only one word in a single line, but it messes up when there are multiple words. Any help is appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
# define MAX 255
int Find_Number_Words_in_Line( char str[MAX] )
{
char *ptr;
int count = 0;
int j;
/* advance character pointer ptr until end of str[MAX] */
/* everytime you see the space character, increase count */
/* might not always work, you'll need to handle multiple space characters before/between/after words */
ptr = str;
for ( j = 0; j < MAX; j++ )
{
if ( *ptr == ' ' )
count++;
else if (( *ptr == '\0' ) || ( *ptr == '\n' ))
break;
ptr++;
}
return count;
}
void Extract_Word_From_Line_Based_on_Position( char line[MAX], char word[MAX], const int position )
{
char *ptr;
/* move pointer down line[], counting past the number of spaces specified by position */
/* then copy the next word from line[] into word[] */
}
int Is_Palindrome ( char str[MAX] )
{
/* check if str[] is a palindrome, if so return 1, else return 0 */
}
int main(int argc, char **argv)
{
FILE *data_file;
FILE *result_file;
char *line_from_data_file = (char*)malloc(MAX);
char *word = (char*)malloc(MAX);
const char *dat = argv[1];
const char *res = argv[2];
int j, n;
if (argc != 3)
{
printf("Wrong parameters");
return 0;
}
data_file = fopen(dat, "r");
result_file = fopen(res, "w");
fgets( line_from_data_file, MAX, data_file );
while ( ! feof( data_file ) )
{
/*
fgets returns everything up to newline character from data_file,
function1 in original context would only run once for each line read
from data_file, so you would only get the first word
function1( line_from_data_file, word );
fputs( word, result_file );
fgets( line_from_data_file, MAX, data_file );
instead try below, you will need to write the code for these new functions
don't be afraid to name functions in basic English for what they are meant to do
make your code more easily readable
*/
n = Find_Number_Words_in_Line( line_from_data_file );
for ( j = 0; j < n; j++ )
{
Extract_Word_From_Line_Based_on_Position( line_from_data_file, word, n );
if ( Is_Palindrome( word ) )
fputs( word, result_file ); /* this will put one palindrome per line in result file */
}
fgets( line_from_data_file, MAX, data_file );
}
free( line_from_data_file );
free( word );
fclose( data_file );
fclose( result_file );
return 0;
}
To follow up from the comments, you may be overthinking the problem a bit. To check whether each word in each line of a file is a palindrome, you have a 2 part problem. (1) reading each line (fgets is fine), and (2) breaking each line into individual words (tokens) so that you can test whether each token is a palindrome.
When reading each line with fgets, a simple while loop conditioned on the return of fgets will do. e.g., with a buffer buf of sufficient size (MAXC chars), and FILE * stream fp open for reading, you can do:
while (fgets (buf, MAXC, fp)) { /* read each line */
... /* process line */
}
(you can test the length of the line read into buf is less than MAXC chars to insure you read the complete line, if not, any unread chars will be placed in buf on the next loop iteration. This check, and how you want to handle it, is left for you.)
Once you have your line read, you can either use a simple pair of pointers (start and end pointers) to work your way through buf, or you can use strtok and let it return a pointer to the beginning of each word in the line based on the set of delimiters you pass to it. For example, to split a line into words, you probably want to use delimiters like " \t\n.,:;!?" to insure you get words alone and not words with punctuation (e.g. in the line "sit here.", you want "sit" and "here", not "here.")
Using strtok is straight forward. On the first call, you pass the name of the buffer holding the string to be tokenized and a pointer to the string containing the delimiters (e.g. strtok (buf, delims) above), then for each subsequent call (until the end of the line is reached) you use NULL as name of the buffer (e.g. strtok (NULL, delims)) You can either call it once and then loop until NULL is returned, or you can do it all using a single for loop given that for allows setting an initial condition as part of the statement, e.g., using separate calls:
char *delims = " \t\n.,:;"; /* delimiters */
char *p = strtok (buf, delims); /* first call to strtok */
while ((p = strtok (NULL, delims))) { /* all subsequent calls */
... /* check for palindrome */
}
Or you can simply make the initial call and all subsequent calls in a for loop:
/* same thing in a single 'for' statement */
for (p = strtok (buf, delims); p; p = strtok (NULL, delims)) {
... /* check for palindrome */
}
Now you are to the point you need to check for palindromes. That is a fairly easy process. Find the length of the token, then either using string indexes, or simply using a pointer to the first and last character, work from the ends to the middle of each token making sure the characters match. On the first mismatch, you know the token is not a palindrome. I find a start and end pointer just as easy as manipulating sting indexes, e.g. with the token in s:
char *ispalindrome (char *s) /* function to check palindrome */
{
char *p = s, /* start pointer */
*ep = s + strlen (s) - 1; /* end pointer */
for ( ; p < ep; p++, ep--) /* work from end to middle */
if (*p != *ep) /* if chars !=, not palindrome */
return NULL;
return s;
}
If you put all the pieces together, you can do something like the following:
#include <stdio.h>
#include <string.h>
enum { MAXC = 256 }; /* max chars for line buffer */
char *ispalindrome (char *s);
int main (int argc, char **argv) {
char buf[MAXC] = "", /* line buffer */
*delims = " \t\n.,:;"; /* delimiters */
unsigned ndx = 0; /* line index */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line */
char *p = buf; /* pointer to pass to strtok */
printf ("\n line[%2u]: %s\n tokens:\n", ndx++, buf);
for (p = strtok (buf, delims); p; p = strtok (NULL, delims))
if (ispalindrome (p))
printf (" %-16s - palindrome\n", p);
else
printf (" %-16s - not palindrome\n", p);
}
if (fp != stdin) fclose (fp);
return 0;
}
char *ispalindrome (char *s) /* function to check palindrome */
{
char *p = s, *ep = s + strlen (s) - 1; /* ptr & end-ptr */
for ( ; p < ep; p++, ep--) /* work from end to middle */
if (*p != *ep) /* if chars !=, not palindrome */
return NULL;
return s;
}
Example Input
$ cat dat/palins.txt
abcba rttt plllp
aaaaaaaaaaaa
ababa
abbbba
kede
Example Use/Output
$ ./bin/palindrome <dat/palins.txt
line[ 0]: abcba rttt plllp
tokens:
abcba - palindrome
rttt - not palindrome
plllp - palindrome
line[ 1]: aaaaaaaaaaaa
tokens:
aaaaaaaaaaaa - palindrome
line[ 2]: ababa
tokens:
ababa - palindrome
line[ 3]: abbbba
tokens:
abbbba - palindrome
line[ 4]: kede
tokens:
kede - not palindrome
Look things over and think about what it taking place. As mentioned above, insuring you have read a complete line in each call with fgets should be validated, that is left to you. (but with this input file -- of course it will) If you have any questions, let me know and I'll be happy to help further.
In order to complete a program I am working on, I have to be able to put pieces of a string into a stack for later use. For example, say I had this string:
"22 15 - 2 +"
Ideally, I first want to extract 22 from the string, place it in a separate, temporary string, and then manipulate it as I would like. Here is the code that I'm using which I think would work, but it is very over-complicated.
void evaluatePostfix(char *exp){
stack *s = initStack();
char *temp_str;
char temp;
int temp_len, val, a, b, i=0, j;
int len = strlen(exp);
while(len > 0){
temp_str = malloc(sizeof(char)); //holds the string i am extracting
j=0; //first index in temp_str
temp = exp[i]; //current value in exp, incremented later on the function
temp_len = 1; //for reallocation purposes
while(!isspace(temp)){ //if a white space is hit, the full value is already scanned
if(ispunct(temp)) //punctuation will always be by itself
break; //break if it is encountered
temp_str = (char*)realloc(temp_str, temp_len+1); //or else reallocate the string to hold the new character
temp_str[j] = temp; //copy the character to the string
temp_len++; //increment for the length of temp_str
i++; //advance one value in exp
j++; //advance one value in temp_str
len--; //the number of characters left to scan is one less
temp = exp[i]; //prepare for the next loop
} //and so on, and so on...
} //more actions follow this, but are excluded
}
Like I said, overcomplicated. Is there a simpler way for me to extract this code? I can reliably depend upon there being white space between the values and characters I need to extract.
If you are good to use library function, then strtok is for this
#include <string.h>
#include <stdio.h>
int main()
{
char str[80] = "22 15 - 2 +";
const char s[2] = " ";
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, s);
}
return(0);
}
Reference
The limitation of strtok(char *str, const char *delim) is that it can't work on multiple strings simultaneously as it maintains a static pointer to store the index till it has parsed (hence sufficient if playing with only one string at a time). The better and safer method is to use strtok_r(char *str, const char *delim, char **saveptr) which explicitly takes a third pointer to save the parsed index.
#include <string.h>
#include <stdio.h>
int main()
{
char str[80] = "22 15 - 2 +";
const char s[2] = " ";
char *token, *saveptr;
/* get the first token */
token = strtok_r(str, s, &saveptr);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok_r(NULL, s, &saveptr);
}
return(0);
}
Take a look at the strotk function, i think it's what you'r looking for.
Im having a lot of trouble printing up to the string and then replacing the word and then printing the rest of the string. I want to replace the "word" variable with \e[7m word \e[0m. I tried using strcasestr to get to to where word is in the string, and it returns a pointer starting at the string. My question is how do I use this pointer to print the string up to that point, replace the word with \e[7m word \e[0m, then print the rest of the string
struct node *ptr;
int count = 0;
char* filecheck = "";
char* tester = "";
char* pch = "";
char str[1024];
int i;
int j;
int charcount = 0;
int counter = 1;
FILE *fp = fopen(ptr->fileName, "r");
char line [ 1024 ]; /* or other suitable maximum line size */
int counter = 1;
while ( fgets ( line, sizeof line, fp ) != NULL ) /* read a line */{
//print the line
printf("\e[7m %s \e[0m", word);
printf("%s", line);
}
This is a simple way to do it
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char *tester = "Hello my name is Rocky the polar bear";
char *pch = NULL;
char *word = "the";
pch = strcasestr(tester, word);
if (pch != NULL)
{
size_t length;
/* this will give the difference between the pointers */
length = pch - tester;
/* write to stdout from the start of the string just 'length' bytes */
fwrite(tester, 1, length, stdout);
/* write the word you want to substitute */
printf("\033[7m%s\033[0m", word);
/* pch is pointing to the start of 'word' in the string, advance to it's end */
pch += strlen(word);
/* print the rest of the string */
printf("%s", pch);
}
return 0;
}
Printing the part after word is easy: just start at the character strlen(word) characters after where word starts. Printing the replacement is trivial (unless you need to compute the replacement, which you've said nothing about how to do).
That leaves the part before word. If tester didn't have a string constant in it, you could set *pch to 0, terminating the string at the start of word, and just print tester (then put the character you erased back). Instead, you could copy the part of tester to be printed into a character array, and print that.
I have a char array:
char tmp[2048];
I want to cut of the first x words of tmp. I define a word as a sequence of characters that does not include whitespaces. I tried something like this (should cut of the first 3 words):
sscanf(tmp, "%*s %*s %*s %s", tmp);
My problem is, that '%s' stops at the first whitespace it finds. I want the new string to end at the end of the old string, not at the first whitespace.
I'm also open for other suggestions how to cut of the first x words of a string. I define a word as a sequence of characters that doesn't contain whitespaces.
Here's a rough implementation:
const char* TrimWords(const char* input, int nWords)
{
while (nWords)
{
if (!isspace(*input) && isspace(*(input + 1)))
{
nWords--;
}
input++;
}
return input;
}
TrimWords("One Two Three Four Five", 3);
// returns " Four Five" after the first 3 words are trimmed.
Detailed input validation and error checking is left to the OP.
This is just a good starting point.
use strncpy(tmp, n, tmp+m); where m and n are ints
char tmp[20] = "abcdef";
strncpy(tmp, tmp + 3, 2);
for exmaple: code above will result in decdef
You can use strtok to tokenize strings by whitespace. Something similar to this could do what you're trying to achieve:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
// Number of words to trim
const int numWords = 2;
char tmp[1024];
char buffer[1024];
sprintf(tmp, "this is a\tsentence.");
strcpy(buffer, tmp);
char* token = strtok(buffer, " \t");
for (int i = 0; i < numWords && token; i++) {
token = strtok(NULL, " \t");
}
if (token) {
size_t len = 1024 - (token - buffer);
memmove(tmp, tmp + (token - buffer), len);
}
else {
memset(tmp, '\0', 1024);
}
// Prints "a sentence."
printf("%s", tmp);
return 0;
}
However, the use of strtok is tricky at best. I would suggest using an approach similar to that of abelenky's answer.
I have following code:
int main(){
char sentence[] = "my name is john";
int i=0;
char ch[50];
for (char* word = strtok(sentence," "); word != NULL; word = strtok(NULL, " "))
{
// put word into array
// *ch=word;
ch[i]=word;
printf("%s \n",ch[i]);
i++;
//Above commeted part does not work, how to put word into character array ch
}
return 0;
}
I am getting error: error: invalid conversion from ‘char*’ to ‘char’ [-fpermissive]
I want to store each word into array, can someone help?
To store a whole set of words you need an array of words, or at least an array of pointers pointing to a word each.
The OP's ch is an array of characters and not an array of pointers to characters.
A possible approach would be:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define WORDS_MAX (50)
int main(void)
{
int result = EXIT_SUCCESS;
char sentence[] = "my name is john";
char * ch[WORDS_MAX] = {0}; /* This stores references to 50 words. */
char * word = strtok(sentence, " "); /* Using the while construct,
keeps the program from running
into undefined behaviour (most
probably crashing) in case the
first call to strtok() would
return NULL. */
size_t i = 0;
while ((NULL != word) && (WORDS_MAX > i))
{
ch[i] = strdup(word); /* Creates a copy of the word found and stores
it's address in ch[i]. This copy should
be free()ed if not used any more. */
if (NULL == ch[i])
{
perror("strdup() failed");
result = EXIT_FAILURE;
break;
}
printf("%s\n", ch[i]);
i++;
word = strtok(NULL, " ")
}
return result;
}