I want to return nothing when the string is number
here is my code,
#include <string.h>
#include <ctype.h>
int num = 0;
char* findWord(char* subString) {
char* word = malloc(sizeof(char) * (strlen(subString) + 1));
int i = 0;
int Position = 0;
num = 0;
while (ispunct(subString[i]) != 0 || isspace(subString[i]) != 0) {
i++;
}
num = i;
while (ispunct(subString[i]) == 0 && isspace(subString[i]) == 0) {
word[Position] = subString[i];
i++;
Position++;
}
word[Position] = '\0';
return word;
}
char** wordList(const char* s) {
int len = strlen(s);
int i = 0;
char* Copyword = malloc(sizeof(char) * len);
strncpy(Copyword, s, len);
char** result = (char**) malloc(sizeof(char*) * (len + 1));
char* word = NULL;
word = findWord(Copyword);
char* wordEnd = Copyword;
while (*word != 0) {
result[i] = word;
wordEnd = wordEnd + strlen(word) + num;
word = findWord(wordEnd);
i++;
}
result[i] = '\0';
free(Copyword);
return result;
}
int main(void) {
char** words = wordList("1 23 456 789");
int i = 0;
while (words[i] != NULL) {
printf("%s\n", words[i]);
free(words[i]); // We're done with that word
i++;
}
free(words); // We're done with the list
return 0;
}
my code is ok when the string is sentence.
however, in this case, I want to print nothing(just like a space) when the string is number.
but what I go is
1
23
456
789
I expect to get
nothing shows here! just a space
For starters: You pass a non 0-terminated C-"string" (Copyword) to findWord() and in there call strlen() on it. This just doesn't crash your app by bad luck.
Related
I have a char array containing a number.
char number[] = "12000000"
I need to have a function to insert a divider in every 3 digits. Like:
char result[] = "12,000,000"
My function accepts the number as a char pointer and it needs to return result as a char pointer too.
char* insert_divider(char* number) {
some magic;
return result;
}
I have no idea of working with pointers. Thanks.
Here you have a function that adds char c every num characters starting from the end. You need to make sure that the string buffer is long enough to accommodate the amended string.
char *addEvery(char *str, char c, unsigned num)
{
char *end = str;
if(str && *str && num)
{
size_t count = 1;
while(*(end)) end++;
while(end != str)
{
end--;
count++;
if(!(count % (num + 1)) && str != end)
{
memmove(end + 1, end, count);
*end = c;
count++;
}
}
}
return str;
}
int main(void)
{
char str[100] = "120000000000";
printf("%s", addEvery(str,',',3));
}
I came up with this piece of code:
char *result;
result = (char*) malloc(15);
int len= strlen(input);
uint8_t cursor= 0;
for(int i = 0; i < len; i++) {
if ((len- i) > 0 && (len- i) % 3 == 0) {
result[i + cursor] = ',';
cursor++;
}
result[i + cursor] = input[i];
}
result[len+ cursor] = '\0';
Thanks everyone for help and advice.
Here is another way to do it:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* insert_divider(char* number, size_t length) {
int j = length + length/3; // every 3 digits a ',' will be inserted
char *out = (char*)malloc(j + 1);
out[j--] = '\0';
for (int i = length - 1, k = 1; i >= 0; i--, k++) {
out[j--] = number[i];
if ((k%3) == 0) {
out[j--] = ',';
}
}
return out;
}
int main(){
char number[] = "12000000";
char *outNumber = insert_divider(number, strlen(number));
printf("%s", outNumber);
free(outNumber);
return 0;
}
I'm trying to write a code in c that return 1 if there is "&" in the string and 0 otherwise.
In addition, the char* that I receive in the function I want to put it in an array of chars and NULL in the end.
My code is like this:
char** isBackslash(char* s1, int *isFlag) {
int count = 0;
isFlag = 0;
char **s2[100];
char *word = strtok(s1, " ");
while (word != NULL) {
s2[count] = word;
if (!strcmp(s2[count], "&")) {
isFlag = 1;
}
count++;
word = strtok(NULL, " ");
}
s2[count] = NULL;
return s2;
}
For example, if the original string (s1) is "Hello I am John &".
So I want s2 to be like:
s2[0] = Hello
s2[1] = I
s2[2] = am
s2[3] = John
s2[4] = &
s2[5] = NULL
And the function will return '1'. What is wrong with my code? I debugged it and unfortunately, I don't find the problem.
You were shadowing your own parameter. See a working example below:
#include <stdio.h>
#include <string.h>
#define BUFF_SIZE 256
int isBackslash(char* s1, char s2[][BUFF_SIZE]) {
int isFlag = 0;
int i = 0;
int j = 0;
int n = 0;
while (s1[i] != '\0') {
isFlag |= !('&' ^ s1[i]); // will set the flag if '&' is met
if (s1[i] == ' ') {
while (s1[i] == ' ')
i++;
s2[n++][j] = '\0';
j = 0;
}
else
s2[n][j++] = s1[i++];
}
return isFlag;
}
int main(void) {
char s2[BUFF_SIZE/2+1][BUFF_SIZE];
memset(s2, 0, sizeof(s2));
char s1[BUFF_SIZE] = "Hello I am John &";
int c = isBackslash(s1, s2);
printf("%d\n", c);
int i = 0;
while (s2[i][0] != '\0')
printf("%s\n", s2[i++]);
}
I'm trying to split this string:
this is a text file
looking for the word cat
the program should print also cats
and crat and lcat but it shouldn’t
print the word caats
into a two dimensional arrays such that every line in the text is a line in the array.
For example:
lines[0][0] = 't'
lines[0][1] = 'h'
and so on. For now, this is my code:
void print_lines(char txt[]){
char lines[SIZE][SIZE];
int num_of_lines = fill_lines(txt, lines);
printf("lines: %d\n",num_of_lines );
int i;
for (i = 0; i < num_of_lines; i++)
{
printf("%s\n", lines[i]);
}
}
int fill_lines(char txt[], char lines[][]){
char copy[strlen(txt)];
memcpy(copy, txt, strlen(txt));
char *line = strtok(copy, "\n");
int i = 0;
while(line != NULL){
strcpy(lines[i][0], line);
line = strtok(NULL, "\n");
i++
}
return i + 1;
}
The problem I'm currently dealing with is an error in strcpy(lines[i], line) that reads:
expression must be a pointer to a complete object type
I have also tried memcpy(lines[i], line, strlen(line)).
Any help would be much appreciated.
I think this should work for you
Here I used '\n' as a delimiter
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
char **str_split(char *a_str, const char a_delim)
{
char **result = 0;
size_t count = 0;
char *tmp = a_str;
char *last_comma = 0;
char delim[2];
delim[0] = a_delim;
delim[1] = 0;
/* Count how many elements will be extracted. */
while (*tmp)
{
if (a_delim == *tmp)
{
count++;
last_comma = tmp;
}
tmp++;
}
/* Add space for trailing token. */
count += last_comma < (a_str + strlen(a_str) - 1);
/* Add space for terminating null string so caller
knows where the list of returned strings ends. */
count++;
result = malloc(sizeof(char *) * count);
if (result)
{
size_t idx = 0;
char *token = strtok(a_str, delim);
while (token)
{
assert(idx < count);
*(result + idx++) = strdup(token);
token = strtok(0, delim);
}
assert(idx == count - 1);
*(result + idx) = 0;
}
return result;
}
int main()
{
char text[] = "this is a text file\nlooking for the word cat\nthe program should print also cats\nand crat and lcat but it shouldn’t\nprint the word caats";
char **tokens;
printf("ORIGINAL TEXT:\n%s\n\n", text);
tokens = str_split(text, ',');
if (tokens)
{
int i;
for (i = 0; *(tokens + i); i++)
{
printf("%s\n", *(tokens + i));
free(*(tokens + i));
}
printf("\n");
free(tokens);
}
return 0;
}
I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}
I have problem with my alignement. This time I want my program to return words that ends and starts with the same letter. I've wrote something like this, but it seems to return random words.
#include <stdio.h>
#include <string.h>
void main()
{
char str[100];
int i, t, j, len;
printf("Enter a string : ");
scanf("%[^\n]s", str);
len = strlen(str);
str[len] = ' ';
for (t = 0, i = 0; i < strlen(str); i++)
{
if ((str[i] == ' ') && (str[i - 1] == str[0]))
{
for (j = t; j < i; j++)
printf("%c", str[j]);
t = i + 1;
printf("\n");
}
else
{
if (str[i] == ' ')
{
t = i + 1;
}
}
}
}
You can use strtok to split the strings from stdin, then apply a letter checker on each parsed word one at a time.
Something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
int is_start_end(char *word);
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
char str[MAXCHAR];
char *word;
char **all_words;
int words_size = 1, word_count = 0;
int i, found;
all_words = malloc(words_size * sizeof(*all_words));
exit_if_null(all_words, "initial Allocation");
printf("Enter words(enter empty line to terminate):\n");
while (fgets(str, MAXCHAR, stdin) != NULL && strlen(str) != 1) {
word = strtok(str, " \n");
while (word !=NULL) {
if (words_size == word_count) {
words_size *= 2;
all_words = realloc(all_words, words_size * sizeof(*all_words));
exit_if_null(all_words, "Reallocation");
}
all_words[word_count] = malloc(strlen(word)+1);
exit_if_null(all_words[word_count], "Initial Allocation");
strcpy(all_words[word_count], word);
word_count++;
word = strtok(NULL, " \n");
}
}
printf("Words that have equal first and last letters:\n");
found = 0;
for (i = 0; i < word_count; i++) {
if (is_start_end(all_words[i])) {
found = 1;
printf("%s\n", all_words[i]);
}
free(all_words[i]);
all_words[i] = NULL;
}
if (found == 0) {
printf("None Found\n");
}
free(all_words);
all_words = NULL;
return 0;
}
int
is_start_end(char *word) {
int len;
len = strlen(word);
if ((len == 1) || (tolower(word[0]) == tolower(word[len-1]))) {
return 1;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
This line removes the null terminator of the string:
len = strlen(str);
str[len] = ' ';
thus the string no longer exists, what is left is just an ordinary array of characters.
The next call to strlen, in the body of the for loop, will cause undefined behavior.