I was checking pointer to pointer, passing it without allocating. I want to allocate a[0]="something str" a[1]="some thing str" a[2]="something str" a[3]="something str" in pp function. Can I do this (allocating and filling with strcpy in pp function) and get it returned back to main?
This is my attempt:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MAX_LEN 100
// float 3
void pp(char *arr, char *delimiter, char **a)
{
int i = 0;
*a = malloc(sizeof(char) * 10);
}
int main(int argc, void **argv)
{
char *arr = "1.77 1.65 1.56 5.555 6.1";
char **f;
pp(arr, " ", &f[0]);
}
I thought I could just allocate individual char * and then populate as strcpy(*(a+x),"something") but it causes segfaults at *a = malloc(sizeof(char) * 10);.
You have multiple bugs in your code.
You do not initialized f but access f[0].
You allocate memory for 10 single char but not for pointers in your function.
Also the overall approach is broken.
You could try like this:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MAX_LEN 100
void pp(char *arr,char *delimiter,char ***a)
{
// TODO: Handle NULL pointers.
int i=0;
// TODO: Calculate number of strings using arr and delimiter...
int num = 10;
*a=malloc((num+1) * sizeof(**a));
for (int k = 0; k < num; k++)
{
(*a)[k] = malloc( 1+ length of string to copy) ;
strcpy((*a)[k], <string to copy>);
}
(*a)[num] = NULL; // indicate end of array.
}
int main(int argc,void **argv)
{
char *arr="1.77 1.65 1.56 5.555 6.1";
char **f;
pp(arr, " ", &f);
int i = 0;
while (f[i] != NULL)
{
printf("string #%d: %s\n", i, f[i]);
i++;
}
}
You should also think about a way how to report the number of found substrings back to the caller. In the example I added an extra pointer holding NULL to terminate the array.
For starters the header <malloc.h> is not a standard C header. Instead use header <stdlib.h>.
Aa for your task
yes that what I will eventually do. Basically array that holds float
then you can use the approach shown in the demonstration program below
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t split( const char *s, const char *delim, double **a )
{
*a = NULL;
size_t n = 0;
for ( const char *p = s; p += strspn( p, delim ), *p != '\0'; )
{
++n;
p += strcspn( p, delim );
}
if ( n != 0 && ( *a = malloc( n * sizeof( double ) ) ) != NULL )
{
char *endptr;
for ( size_t i = 0; i < n; i++ )
{
( *a )[i] = strtod( s, &endptr );
s = endptr;
}
}
return n;
}
int main( void )
{
char *s= "1.77 1.65 1.56 5.555 6.1";
double *a;
size_t n = split( s, " \t", &a );
if ( a != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
printf( "%.3f ", a[i] );
}
putchar( '\n' );
}
free( a );
}
The program output is
1.770 1.650 1.560 5.555 6.100
Actually the function can be more complicated because you will need to check that conversion to double were suvvessful.
Related
I am trying to write a program that compares strings by their length and sorts them with qsort. I have been able to make them sort alphabetically, now I'm trying to sort them by length. What am I doing wrong with my comparison method? I'm unsure about pointers and feel that issue lies there. Thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int stringCmp(const void *str1, const void *str2); //Function prototype.
int main (int argc, char *argv[])
{
int i;
char **arr = malloc(argc * sizeof(char *));
printf("Original Args:\n");
for (i = 0; i < argc-1; i++){
arr[i] = argv[i+1];
printf("%s\n",arr[i]);
}
qsort(arr, argc-1, sizeof *arr, stringCmp);
printf("\nSorted Args:\n");
for (i = 0; i < argc-1; i++){
printf("%s\n", arr[i]);
}
free (arr);
return 0;
}
int stringCmp(const void *str1, const void *str2)
{
return strlen(str1) - strlen(str2);
// return strcmp(*(char **)str1,*(char**) str2);
}
As with the commented out call to strcmp, the pointers received by the function actually have type char ** so you need to cast to that type.
return strlen(*(char **)str1) - strlen(*(char **)str2);
It seems you need to allocate argc - 1 pointers instead of argc pointers
char **arr = malloc( ( argc - 1 ) * sizeof(char *));
As for the comparison function then it can be defined the following way
int cmp( const void *s1, const void *s2 )
{
size_t n1 = strlen( *( const char ** )s1 );
size_t n2 = strlen( *( const char ** )s2 );
return ( n2 < n1 ) - ( n1 < n2 );
}
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cmp( const void *s1, const void *s2 )
{
size_t n1 = strlen( *( const char ** )s1 );
size_t n2 = strlen( *( const char ** )s2 );
return ( n2 < n1 ) - ( n1 < n2 );
}
int main(void)
{
char * s[] = { "12345", "1234", "123", "12", "1" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
qsort( s, N, sizeof( *s ), cmp );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s ", s[i] );
}
putchar( '\n' );
}
The program output is
12345 1234 123 12 1
1 12 123 1234 12345
Pay attention to that to implements the comparison function like
return strlen(*(char **)str1) - strlen(*(char **)str2);
will be incorrect because values of an expression of the unsigned integer type size_t can not be negative. And conversion such a value to the type int results in undefined behavior.
I need to create a character double pointer that will have 401 character arrays.
Will char *xx[401] work, or will I have to use malloc and friends? If so, how should I do it?
With
char *xx[401];
you are declaring an array of 401 pointers to char. All of them will need to be initialized to some other existing char array, for example in this way
char foo[20] = "Hello";
xx[107] = foo;
or malloc'ed, if they are intended to be a dynamically allocated array of strings.
If all these mallocs bother you, you can always define it statically
char xx[401][20+1] = { 0 };
/* Population of element at index 137 with a string defined somewhere else in the code: */
char str[] = "Hi guys";
strncpy(xx[123], str, 20);
(in this example every string will be of the fixed length of 20+1). But it will have to be a global variable: placing it in the stack wouldn't be the best solution.
To make it clear you can rewrite this declaration
char *xx[401];
like
char * ( xx[401] );
That is it is an array with 401 elements of the type char *.
A pointer to this array will look like
char * ( *pxx )[401] = &xx;
Pointer to the element of the array will look like
char ** pxx = xx;
If you want to allocate dynamically an array with 401 elements of the type char * then the code can look like
char ** pxx = malloc( 401 * sizeof( char * ) );
Here is a demonstrative program that shows how an array of pointers to character arrays can be dynamically allocated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
enum { N = 2, M = 6 };
const char * hello[N] = { "Hello", "World" };
char **s = malloc( N * sizeof( char * ) );
for ( size_t i = 0; i < N; i++ )
{
s[i] = malloc( M );
strcpy( s[i], hello[i] );
}
for ( size_t i = 0; i < N; i++ )
{
if ( i != 0 ) putchar( ' ' );
printf( "%s", s[i] );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
free( s[i] );
}
free( s );
return 0;
}
The program output is
Hello World
#include <stdio.h>
#include <string.h>
//reversal function
void reverseString(char* str)
{
int l, i;
char *begin_ptr, *end_ptr, ch;
l = strlen(str);
begin_ptr = str;
end_ptr = str;
//move the ptr to the final pos
for (i = 0; i < l - 1; i++)
end_ptr++;
//pointer swaping
for (i = 0; i < l / 2; i++)
{
ch = *end_ptr;
*end_ptr = *begin_ptr;
*begin_ptr = ch;
begin_ptr++;
end_ptr--;
}
}
// Driver code
---------------------------------main---------------------------------------------------------------------------------------------------
the function call sends the address of the first string in the array
int main()
{
char *str[ ] = {"To err is human...","But to really mess things up...","One needs to know C!!"};
for(int i=0;i<3;i++)
{
reverseString(str[i]); //funtion call
printf("Reverse of the string: %s\n", str[i]);
}
return 0;
}
You may not modify a string literal. Any attempt to modify a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
You should declare a to-dimensional array like
enum { N = 32 };
char str[][N] =
{
"To err is human...",
"But to really mess things up...",
"One needs to know C!!"
};
Pay attention to that the function revreseString is too complicated. Also it is better when the function returns pointer to the reversed string. The function can be defined the following way using pointers
char * reverseString( char *s )
{
if ( *s )
{
for ( char *p = s, *q = s + strlen( s ); p < --q; ++p )
{
char c = *p;
*p = *q;
*q = c;
}
}
return s;
}
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
char * reverseString( char *s )
{
if ( *s )
{
for ( char *p = s, *q = s + strlen( s ); p < --q; ++p )
{
char c = *p;
*p = *q;
*q = c;
}
}
return s;
}
int main(void)
{
enum { N = 32 };
char s[][N] =
{
"To err is human...",
"But to really mess things up...",
"One needs to know C!!"
};
for ( size_t i = 0; i < sizeof( s ) / sizeof( *s ); i++ )
{
puts( reverseString( s[i] ) );
}
return 0;
}
The program output is
...namuh si rre oT
...pu sgniht ssem yllaer ot tuB
!!C wonk ot sdeen enO
I am trying to insert a string by replacing a substring in the (original) string with a new string (toInsert). The start parameter is the starting position of the substring I want to replace. Note: This is part of a larger program but I am just trying to get this function to work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROW 5
#define COLUMN 81
void insertString(char original[], int start, int length, char toInsert[]){
char buffer[COLUMN];
int i = 0;
for (i=0; i<strlen(original); ++i){
if (i>=start){
buffer[i] = toInsert[i];
}
else{
buffer[i] = original[i];
}
}
buffer[strlen(buffer)-1] = '\0';
printf("%s\n", buffer);
return;
}
int main()
{
char rep[COLUMN] = "very";
char sub[COLUMN] = "are";
char buf[ROW][COLUMN] = {
{"How are you doing"}
};
int len = strlen(sub);
int start = 4;
insertString(buf[0], start, len, rep);
return 0;
}
The problem is it only prints "How".
I want it to print "How very you doing"
Also, I have tried using strcpy but that just gives errors/warnings (something to do with pointers and I don't want to deal with pointers because I have not learned about them yet.)
Your function does not make great sense because it neither enlarge or shrink the original string though it has to do this.
And moreover it has undefined behavior due to this if statement because when i is equal to or greater than start you can access the memory beyond the string toInsert using the index i.
if (i>=start){
buffer[i] = toInsert[i];
}
It is simpler to write the function using standard C functions.
Here you are
#include <stdio.h>
#include <string.h>
char * replaceString( char *s1, size_t pos, size_t n, const char *s2 )
{
size_t n1 = strlen( s1 );
if ( pos < n1 )
{
size_t n2 = strlen( s2 );
if ( n != n2 )
{
memmove( s1 + pos + n2, s1 + pos + n, n1 - pos - n + 1 );
}
memcpy( s1 + pos, s2, n2 );
}
return s1;
}
int main(void)
{
{
char s1[100] = "ab1111cd";
const char *s2 = "22";
puts( replaceString( s1, 2, 4 , s2 ) );
}
{
char s1[100] = "ab11cd";
const char *s2 = "2222";
puts( replaceString( s1, 2, 2 , s2 ) );
}
{
char s1[100] = "ab11cd";
const char *s2 = "22";
puts( replaceString( s1, 2, 2 , s2 ) );
}
return 0;
}
The program output is
ab22cd
ab2222cd
ab22cd
If to insert this code block
{
char s1[100] = "How are you doing";
const char *s2 = "very";
puts( replaceString( s1, 4, 3 , s2 ) );
}
in the demonstrative program you will get the output
How very you doing
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stdbool.h>
int compare (const void *a, const void * b){
return ( *(char *)a - *(char *)b ); }
// A utility function two swap two characters a and b
void swap (char* a, char* b)
{
char t = *a;
*a = *b;
*b = t; }
int findCeil (char str[], char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
int i;
// Now iterate through rest of the elements and find
// the smallest character greater than 'first'
for (i = l+1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
FILE *fp;
fp = fopen("out.txt","w+");
char buffer[100];
memset(buffer,'\0',100);
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
setvbuf(str, buffer, _IONBF, 1024);
printf ("%s \n", str);
fprintf(fp,"%s\n",buffer);
// Find the rightmost character which is smaller than its next
// character. Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such chracter, all are sorted in decreasing order,
// means we just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in right of first character.
// Ceil of a character is the smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// Sort the string on right of 'first char'
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
fclose(fp);
}
}
int main()
{
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
Hi ,I am trying jumble solver .I want to store the result of permutation to a buffer and then from buffer to some file,so that I can compare it with dictionary. getting errors for setvbuf.
My C is very rusty,not able to get the desired results.
there are plenty of errors. First you use setvbuf with wrong arguments and do that in cycle. Then you fprintf buffer value instead of str. And also close file in cycle.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare (const void *a, const void * b) {
return ( *(char *)a - *(char *)b );
}
void swap (char* a, char* b) {
char t = *a;
*a = *b;
*b = t;
}
int findCeil (const char str[], char first, int l, int h) {
int ceilIndex = l;
int i;
for (i = l+1; i <= h; i++) {
if (str[i] > first && str[i] < str[ceilIndex]) {
ceilIndex = i;
}
}
return ceilIndex;
}
void sortedPermutations ( char str[] ) {
FILE *fp;
char buffer[1024];
int size = strlen(str);
int isFinished = 0;
fp = fopen("out.txt","w+");
memset(buffer, 0, 100);
qsort( str, size, sizeof( str[0] ), compare );
setvbuf(fp, buffer, _IOFBF, 1024);
while ( !isFinished ) {
int i;
printf("%s \n", str);
fprintf(fp, "%s\n", str);
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1]) {
break;
}
if ( i == -1 ) {
isFinished = 1;
} else {
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
swap( &str[i], &str[ceilIndex] );
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
}
fclose(fp);
}
int main() {
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
setvbuf is used to set custom buffer. It is used, for example, to set big buffer and to have direct access to it. fprintf will print to file only when buffer is full, or when you flush, or close file. And you also use _IONBF which means that stream is not buffered at all.
So - it works only, because it is not buffered, as you send buffer [100], and then try to print 1024. So also change size of buffer to 1024 and use _IOFBF.