arrays and strings in c - c

I would like break up a string sequence by " " and stick it into an array. This is the code that I have but does not work:
int main(void) {
char s[] = "this is a string";
char* x = NULL;
unsigned int i = 0;
for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " ")) {
x[i] = *p;
puts(x[i]);
i++;
}
return 0;
}
It gives me the following error: error:
array initializer must be an initializer list
I am at a loss on how to accomplish this in C. So I would like x[0] = "this",
x[1] = "is" and so on. Any help would be appreciated, I have searched for the answer and read tutorials but still cant come up with the right answer. Any help would be greatly appreciated. Thanks!

There are two problems with your code:
You are trying to grow your array as you go. This is not possible in C without using dynamic allocation with realloc, or pre-allocating sufficient space, and using some of it.
You are trying to store the results of strtok for future use. In general, this is not safe, because tokens point to the original string. It is safer to copy each token into separate space.
Here is how your code would look with pre-allocated space for 100 tokens:
int main(void) {
char s[] = "this is a string";
char* x[100];
unsigned int i = 0;
for (char *p = strtok(s," "); i != 100 && p != NULL; p = strtok(NULL, " ")) {
x[i] = malloc(strlen(p)+1);
strcpy(x[i], p);
puts(x[i]);
i++;
}
// Now you need to free the strings
for (unsigned int j = 0 ; j != i ; j++) {
free(x[j]);
}
return 0;
}
Demo.
If you are certain that there would be no modifications done to s, you could store tokens directly, too:
int main(void) {
char s[] = "this is a string";
char* x[100];
unsigned int i = 0;
for (char *p = strtok(s," "); i != 100 && p != NULL; p = strtok(NULL, " ")) {
x[i] = p;
puts(x[i]);
i++;
}
return 0;
}

Related

Reversing string with char aaryas

I'm learning C now, and i have one question in my program.
I need to reverse string like
I like dogs -> I ekil sgod
I wrote this code
char end[MAX_LEN];
char beg[MAX_LEN];
char* piece = strtok(str, " ");
strcpy(end, piece);
strcpy(beg, piece);
char* pbeg = beg;
char* prev = piece;
int n = strlen(piece)-1;
i = 0;
int n = 0;
while (piece != NULL) {
//printf("\n%s", piece);
while (piece[i] != '\0') {
*(prev + n -i ) = *(pbeg + i);
i++;
}
printf("\n%s", piece);
piece = strtok(NULL, " ");
strcpy(beg, piece); // also in this moment in debugging i saw this error ***Exception thrown at 0x7CBAF7B3 (ucrtbased.dll) in лаб131.exe: 0xC0000005: Access violation reading location 0x00000000.***
}
But it returns only the first lexeme reversed.
You are getting an exception because you are not checking whether the pointer piece is equal to NULL when you are using it in the call of strcpy
piece = strtok(NULL, " ");
strcpy(beg, piece);
Also within the while loop you forgot to reset the variables i and n and the pointer prev.
To use the function strtok is a bad idea because the source string can contain adjacent space characters that should be preserved in the result string. Also you have too many arrays and pointers that only confuse readers of the code.
Here is a demonstration program that shows how the task can be easy done.
#include <stdio.h>
#include <string.h>
void reverse_n( char s[], size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n-i-1];
s[n-i-1] = c;
}
}
int main(void)
{
char input[] = "I like dogs";
const char *separator = " \t";
for ( char *p = input; *p; )
{
p += strspn( p, separator );
char *q = p;
p += strcspn( p, separator );
reverse_n( q, p - q );
}
puts( input );
return 0;
}
The program output is
I ekil sgod

Print pointer string which is return from function in C

Trying to write a C program to reverse the given string (using Pointer) and here is the code.
[sample.c]
#include <stdio.h>
#include <stdlib.h>
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
return i;
}
char *_reverse(char s[])
{
int len = _len(s);
char *r = malloc(len * sizeof(char));
for (int i=len-1; i >= 0; i--) {
*r++ = s[i];
}
*r = '\0'; // Line 21
r -= len; // Line 22
return r;
}
int main(int argc, char *argv[])
{
char s[10] = "Hello";
printf("Actual String: %s\n", s);
printf("Reversed: %s\n", _reverse(s));
return 0;
}
Current O/P:
Actual String: Hello
Reversed: (null)
Expected O/P:
Actual String: Hello
Reversed: olleH
What is wrong or missing in here..? Please correct me. Thanks in advance.
You are modifying the pointer "r" of your newly allocated memory. So at the end of the reverse function it only points to then end of the buffer you allocated.
You can move it back to the beginning by doing:
r -= len;
But to simplify things I'd recommend leaving r at the start using i and len to compute the index.
Also, you don't terminate the reversed string with a '\0'.
You increase r in the loop, then return it. Obviously, it points to an address after the actual reversed string. Copy r to another variable after malloc and return that.
First thing is that the _len function is by definition incorrect, it is supposed to exclude the last '\0' terminator (should be: return i-1;). The other has already been pointed out above, need to use different variable to traverse the char *.
#include <stdio.h>
#include <stdlib.h>
int _len(char s[]) {
int i = 0;
while (s[i++] != '\0');
return i-1;
}
char *_reverse(char s[]) {
int len = _len(s);
//printf("Len: %d\n", len);
char *r = (char *) malloc((len+1) * sizeof(char));
char *ptr = r;
for (int i=len-1; i >= 0; i--) {
//printf("%d %c\n", i, s[i]);
*(ptr++) = s[i];
}
*(ptr++) = '\0';
return r;
}
int main(int argc, char *argv[]) {
char s[10] = "Hello";
printf("Actual String: %s\n", s);
printf("Reversed: %s\n", _reverse(s));
return 0;
}
Actual String: Hello
Reversed: olleH
The first function implementation
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
return i; // Old code
}
though has no standard behavior and declaration nevertheless is more or less correct. Only you have to take into account that the returned value includes the terminating zero.
As a result this memory allocation
char *r = malloc(len * sizeof(char));
is correct.
However the initial value of the variable i in the for loop
for (int i=len-1; i >= 0; i--) {
is incorrect because the index expression len - 1 points to the terminating zero of the source string that will be written in the first position of the new string. As a result the new array will contain an empty string.
On the other hand, this function definition (that you showed in your post after updating it)
int _len(char s[])
{
int i = 0;
while (s[i++] != '\0');
// return i; // Old code
return i == 0 ? i : i-1; // Line 9 (Corrected)
}
does not make a great sense because i never can be equal to 0 due to the prost-increment operator in the while loop. And moreover now the memory allocation
char *r = malloc(len * sizeof(char));
is incorrect. There is no space for the terminating zero character '\0'.
Also it is a bad idea to prefix identifiers with an underscore. Such names can be reserved by the system.
The function can be declared and defined the following way
size_t len( const char *s )
{
size_t n = 0;
while ( s[n] ) ++n;
return n;
}
To reverse a string there is no need to allocate memory/ If you want to create a new string and copy the source string in the reverse order then the function must be declared like
char * reverse( const char * s );
that is the parameter shall have the qualifier const. Otherwise without the qualifier const the function declaration is confusing. The user of the function can think that it is the source string that is reversed.
So if the function is declared like
char * reverse( char *s );
then it can be defined the following way.
char * reverse( char *s )
{
for ( size_t i = 0, n = len( s ); i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = c;
}
return s;
}
If you want to create a new string from the source string in the reverse order then the function can look like
char * reverse_copy( const char *s )
{
size_t n = len( s );
char *result = malloc( len + 1 );
if ( result != NULL )
{
size_t i = 0;
while ( n != 0 )
{
result[i++] = s[--n];
}
result[i] = '\0';
}
return result;
}
And you should not forget to free the result array in main when it is not needed any more.
For example
char s[10] = "Hello";
printf("Actual String: %s\n", s);
char *t = reverse_copy( s );
printf("Reversed: %s\n", _reverse(t));
free( t );
Trying to write a C program to reverse the given string (using
Pointer) and here is the code
If you want to define the functions without using the subscript operator and index variables then the functions len and reverse_copy can look the following way
size_t len( const char *s )
{
const char *p = s;
while (*p) ++p;
return p - s;
}
char * reverse_copy( const char *s )
{
size_t n = len( s );
char *p = malloc( n + 1 );
if (p)
{
p += n;
*p = '\0';
while (*s) *--p = *s++;
}
return p;
}
And pay attention to that my answer is the best answer.:)

How do I enter int elements in an array delimited by spaces in C?

I've been reading the several answers in this page regarding this issue, but none of them hace been useful to me. Also I read:
https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
https://www.tutorialspoint.com/c_standard_library/c_function_atoi.htm
I want the code to read an N number of (INT) values in a single line and then store it in an array.
So far I did the following:
int main() {
int n;
char arr[n];
int arrInt[n];
const char s[2] = " ";
char* token;
int i = 0;
scanf("%n", &n);
scanf("%c", arr);
token = strtok(arr, s);
while (token != NULL)
{
arrInt[i] = atoi(token);
i++;
token = strtok(NULL, s);
}
}
Since the question says the numbers are delimited by spaces, one of the way to do this is by the following method
int main() {
int n;
scanf("%d",&n);
int arr[n];
for(int i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
//for checking
for(int i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
}
I think you missed some points when you were writing your code.
char arr[n];
int arrInt[n];
A array cannot be defined in this way by C standards. This is a service that is removed by the standards but offered by compilers as an extension. This is called VLA. Variable Length Array
scanf("%c", arr);
With this use, you can only get one character. You can't keep a string in the array. If you want to keep string in an array, you can review the following code.
char* sgets(char *p)
{
char *pret = p;
int c;
while ((c = getchar()) != '\n' && c != EOF)
*p++ = (char)c;
*p = '\0';
return pret;
}
I wrote a code like this so that you can keep the strings:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char arr[] = "Hi Hello How Where";
char *token = strtok(arr, " ");
char **d_arr = malloc(sizeof(char *) * 1);
d_arr[0] = token;
int count = 1;
while (token != NULL)
{
token = strtok(NULL, " ");
d_arr = realloc(d_arr, sizeof(char *) * (count + 1));
d_arr[count++] = token;
}
for(int i = 0; i < count-1; ++i)
printf("%s ", d_arr[i]);
}
I misunderstood the question. I hope what I write helps. :(

C: Same chars from two strings

I have two strings:
char *str1 = "this is a test";
char *str2 = "ts bd a";
I'm trying to write a function that returns a new string with the same chars from the two string without duplicates (also ' ' is duplicate). eg.:
char *retStr = GetSameChars(str1, str2); //returns "ts a";
How can I do that?
What I'm tried:
char *GetSameChars(char str1[], char str2[]) {
int found = -1, i , j = 0, biggest, index = 0;
char *retArr, *star = '*';
int str1Len, str2Len, count = 0;
str1Len = strlen(str1);
str2Len = strlen(str2);
biggest = str1Len > str2Len ? str1Len : str2Len;
retArr = (char *)malloc(sizeof(char) * count);
for (i = 0; i < str1Len; i++) {
for (j = 0; j < str2Len; j++) {
if (str1[i] == str2[j] && found == -1) {
count++;
found = j;
} else
if (str2[j] == str2[found])
str2[j] = star; //Throw an exception
}
found = -1;
}
retArr = (char *)malloc(sizeof(char) * count);
j = 0;
for (i = 0; i < str2Len; i++)
if (str2[i] != '*')
retArr[j++] = str2[i];
for (i = 0; i < str2Len; i++)
printf("%c", retArr[i]);
}
When I tried the line str2[j] = star; I got an exception.
What is my mistake?
My recommendations would be: keep it simple; get to know the C standard library; write less, test more.
Some specific problems with your code: you pass the wrong variable to malloc(); you estimate the answer to fit in the size of the larger of the two strings but it will actually fit into the smaller of the two; you modify an argument string str2[j] = star -- you should be treating the arguments as readonly; you malloc() retArr twice unnecessarily, leaking the first one when you allocate the second; your algorithm simply doesn't work.
Although a lookup table, as others have suggested, would be more efficient, let's use the standard library routine strchr() to solve this problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getSameChars(const char *string1, const char *string2) {
size_t string1_length = strlen(string1);
size_t string2_length = strlen(string2);
size_t shortest = string1_length < string2_length ? string1_length : string2_length;
char *common_pointer, *common = malloc(shortest + 1);
*(common_pointer = common) = '\0';
for (size_t i = 0; i < string1_length; i++) {
// character found in both input strings, but not yet in common string
if (strchr(string2, string1[i]) != NULL && strchr(common, string1[i]) == NULL) {
*common_pointer++ = string1[i];
*common_pointer = '\0';
}
}
return common;
}
int main() {
char *stringA = "this is a test";
char *stringB = "ts bd a";
char *result = getSameChars(stringA, stringB);
printf("%s\n", result);
free(result);
return(0);
}
Your code complains because you are trying to assign a pointer to a char, to get the value inside a pointer you need to use the * operator like so:
*star;
a good way to check if a letter have already appeared(if you want to use it on all of the ascii table then 128) is to use a lookup table. first you will need to declare an array the length of all letters in the alphabet like so:
char lut[26];
If it is a global variable then it will be set to 0, then all you need to do is go to the index of the char you got and mark it as 1, a simple if will later be able to determine if a letter has already appeard.
example:
lut[toupper(somechar) - 'A'] = 1;
In this example you set the char in the lookup table that is equivalent to the somechar variable as 1, marking it has already appeared.
hope this helps.

C: split string to string array with delimiter "&&"

I'm kinda new in C so i need help.
I need to split a string to string array with the delimiter "&&",
the thing is that i tried to use strtok, but when i use it, it looks like that the strtok can't handle correctly if the is '&' some where in the string.
I know that each part between the && is at max 256 chars and that there are at most 16 parts.
so i need to create an array arr[16][256] or an array of size 16*256.
in any case each time i try my code fail on the different between & and &&
example:
char arr[16][255];
char stringToSplit = "Hello World && How are u doing && more words & bla &";
output:
arr[0] = "Hello World ";
arr[1] = " How are u doing ";
arr[2] = " more words & bla &";
Thanks ahead!
This is what i tried:
int i;
char *p;
i = 0;
p = strtok (stringToSplit ,"&&");
while (p != NULL)
{
arr[i++] = p;
p = strtok (NULL, "&&");
}
for (i=0;i<16; ++i)
printf("%s\n", arr[i]);
strtok() splits the string on characters.
You need strstr() to find a string inside a string then copy the relevant characters to the destination. Keep doing this until the source string is exhausted.
A simple double nested loop will do. check for "&&" and watch out for long sub-strings and too many sub-strings.
void tubu13(void) {
#define NUM (16)
#define SIZ (255+1)
char arr[NUM][SIZ];
const char *stringToSplit = "Hello World && How are u doing && more words & bla &";
const char *p = stringToSplit;
int n, len;
for (n = 0; n < NUM; n++) {
for (len=0; len < SIZ-1; len++) {
if (p[0] == '\0') {
break;
}
if (p[0] == '&' && p[1] == '&') {
p += 2;
break;
}
arr[n][len] = *p;
p++;
}
arr[n][len] = '\0';
printf(" arr[%d] = \"%s\";\n", n, arr[n]);
}
}
arr[0] = "Hello World ";
arr[1] = " How are u doing ";
arr[2] = " more words & bla &";
arr[3] = "";
...
arr[15] = "";
#include <stdio.h>
#include <string.h>
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
int main(){
char arr[16][255];
char stringToSplit[] = "Hello World && How are u doing && more words & bla &";
int i, n;
char *p;
i = 0;
p = strtokByWord(stringToSplit, "&&");
while (p != NULL){
strcpy(arr[i++], p);
p = strtokByWord(NULL, "&&");
}
n = i;
for (i=0;i<n; ++i)
printf("%s\n", arr[i]);
return 0;
}

Resources