So, I am doing my own rudimentary version of itoa(), and I just realized I don't exactly know how to modify a char* passed as parameter, or if there is something wrong with the way I am doing it...
The way I am doing it is by doing malloc() onto the buffer passed as argument, then write the number into it. This is apparently working before returning from the function (the buffer is printed correctly), but then when trying to print it back in main(), it segfaults.
If I understand the error correctly, I am changing the address buff points to inside with that malloc(), and then modify its contents, but the new malloc'd address inside is not returned. How could I do that without changing the parameters or the return value?
int itoa(int i, char *buff) {
int length = 0;
// get the length
long temp = 1;
while (temp <= i) {
length++;
temp *= 10;
}
buff = malloc(length + 1); // buff will have 'length' chars + one extra (\0)
int j = 0;
do { /* generate digits in reverse order */
buff[j++] = i % 10 + '0'; /* get next digit */
} while ((i /= 10) > 0); /* delete it */
buff[length] = '\0';
// reverse it
int k, l;
char c;
for (k = 0, l = length - 1; k<l; k++, l--) {
c = buff[k];
buff[k] = buff[l];
buff[l] = c;
}
printf("buff's now:%s\n", buff);
return 0;
}
int main() {
char *buff = NULL;
itoa(45, buff);
printf("%s\n", buff);
}
Your pointer isn't modified as it was copied. You can read more here. You can try this code after reading the above link.
#include <stdlib.h>
#include <stdio.h>
int itoa_(int i, char **parabuff)
{
int length = 0;
// get the length
long temp = 1;
while (temp <= i)
{
length++;
temp *= 10;
}
char *buff = malloc(length + 1); // buff will have 'length' chars + one extra (\0)
int j = 0;
do
{ /* generate digits in reverse order */
buff[j++] = i % 10 + '0'; /* get next digit */
} while ((i /= 10) > 0); /* delete it */
buff[length] = '\0';
// reverse it
int k, l;
char c;
for (k = 0, l = length - 1; k < l; k++, l--)
{
c = buff[k];
buff[k] = buff[l];
buff[l] = c;
}
printf("buff's now: %s\n", buff);
*parabuff = buff;
return 0;
}
int main()
{
char *buff = NULL;
itoa_(45, &buff);
printf("buff in main: %s\n", buff);
}
//OUTPUT
buff's now: 45
buff in main: 45
Related
Write a program that determines where to add periods to a decimal string so that the resulting string is a
valid IP address. There may be more than one valid IP address corresponding to a string, in which case you
should print all possibilities. Additionally your program must validate that neither group must not exceed
255.
For example:
If the mangled string is “19216811” then two corresponding IP addresses are 192.168.1.1 and 192.216.81.1.
There are also seven other possible IP addresses for this string.
My program is causin segmentationn fault
My Code:
#include<stdio.h>
#include <string.h>
#include<stdbool.h>
#include<stdlib.h>
bool is_valid_part(char *part) {
return (strlen(part)== 1) || (part[0] != 0 && atoi(part) <= 255);
}
int a =0;
int pos = 0;
void generate(char *ip, char **ans)
{
int l = strlen(ip);
// Check for string size
if (l > 12 || l < 4) {
printf("Not valid IP String");
return;
}
char *check = ip;
// Generating different combinations.
for (int i = 1; i < l - 2; i++) {
for (int j = i + 1; j < l - 1; j++) {
for (int k = j + 1; k < l; k++) {
check = strncpy(check, ip, k); + '.'+ strncpy(check, ip + k, strlen(ip) - k - 1);
check = strncpy(check, ip, j); + '.'+ strncpy(check, ip + j, strlen(ip) - j - 1);
check= strncpy(check, ip, i); + '.'+ strncpy(check, ip + i, strlen(ip) - i - 1);
if (is_valid_part(check)) {
ans[pos++] = check;
printf("%s", check);
}
check = ip;
}
}
}
}
int main(void){
char str[32];
fgets(str, 32, stdin);
printf("%s",str);
char **ans;
generate(str, ans);
}
As the input string str contains a trailing newline character,
strlen(str) is larger than the intended value. You need to chop
the newline character off.
Your is_valid_part() function is very close but you need to
change part[0] != 0 to part[0] != '0' to examine the leading 0.
If you want to create a list of ip addresses at runtime, you need to
allocate memory area with malloc/realloc and free the area after use.
Then would you please try the following:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
bool is_valid_part(char *part) {
return (strlen(part) == 1) || (part[0] != '0' && atoi(part) <= 255);
}
void generate(char *ip, char ***ptr, int *pos)
{
int len = strlen(ip);
char octet[4][4];
char addr[16];
// check for string size
if (len > 12 || len < 4) {
printf("The length must be between 4 and 12\n");
return;
}
// check characters
for (int i = 0; i < len; i++) {
if (! isdigit(ip[i])) {
printf("Invalid character: %c\n", ip[i]);
return;
}
}
// generating different combinations.
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
for (int k = 1; k <= 3; k++) {
int l = len - i - j - k;
if (l < 1 || l > 3) continue;
strncpy(octet[0], ip, i); *(octet[0] + i) = '\0';
strncpy(octet[1], ip + i, j); *(octet[1] + j) = '\0';
strncpy(octet[2], ip + i + j, k); *(octet[2] + k) = '\0';
strncpy(octet[3], ip + i + j + k, l); *(octet[3] + l) = '\0';
int fail = 0;
for (int m = 0; m < 4; m++) {
if (! is_valid_part(octet[m])) fail = 1;
}
if (fail) continue; // skip to next combination
// generate a string of ip address
strcpy(addr, octet[0]);
for (int m = 1; m < 4; m++) {
strcat(addr, ".");
strcat(addr, octet[m]);
}
// printf("%s\n", addr);
// allocate memory and append the string to the list
*ptr = realloc(*ptr, (*pos + 1) * sizeof(char **));
(*ptr)[*pos] = malloc(strlen(addr) + 1);
strcpy((*ptr)[*pos], addr);
(*pos)++; // increment the count of ip addresses
}
}
}
}
int main(void) {
char str[BUFSIZ];
printf("Enter a decimal string: ");
fgets(str, BUFSIZ, stdin);
char *p = rindex(str, '\n'); // trim the newline character
if (p) *p = '\0';
p = rindex(str, '\r'); // trim the carrage return character
if (p) *p = '\0';
// printf("%s\n", str);
char **ans = NULL; // array of ip address strings
int cnt = 0; // counter of the ip addresses
generate(str, &ans, &cnt);
// print the results
for (int i = 0; i < cnt; i++) {
printf("%s\n", ans[i]);
}
// free memory
for (int i = 0; i < cnt; i++) {
free(ans[i]);
}
free(ans);
}
Output:
Enter a decimal string: 19216811
1.92.168.11
19.2.168.11
19.21.68.11
19.216.8.11
19.216.81.1
192.1.68.11
192.16.8.11
192.16.81.1
192.168.1.1
Integer values i, j, k and l are generated such that each value
is between 1 and 3 inclusive and the sum equals to strlen(ip).
Then the string ip is divided into an array octet, each of
length i, j, k and l.
Each substring in octet is terminated with a null character.
If every elements of octet meet the condition, they are concatenated
into an ip address string.
*ptr is a 2-d array which grows on the fly.
As the value of *ptr is modified within the generate() function,
a pointer to ans is passed to the function.
The counter cnt is also passed by address. It is not recommended to
use a global address as long as there are alternatives.
ok that's it, it's been more than 15 hours and i still can't figure out what's going on !
Here is a code for timeconversion problem in hackerrank, a function takes a string (time in 12--hour AM/PM format) and converts it to military (24-hour) time (returning a string)
the problem is exactly in the function char* timeConversion(char* s)
in this line of code
b = strcmp(ampm,"PM");
it always gives me error which i can not understand
"ERROR: invalid read of size 1"
can anyone help me ?!
#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readline();
/*
* Complete the timeConversion function below.
*/
/*
* Please either make the string static or allocate on the heap. For example,
* static char str[] = "hello world";
* return str;
*
* OR
*
* char* str = "hello world";
* return str;
*
*/
/* Swaps strings by swapping pointers */
void swap(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
void reverse(char str[], int length)
{
int start = 0;
int end = length -1;
while (start < end)
{
swap(*(str+start), *(str+end));
start++;
end--;
}
}
// Implementation of itoa()
char* itoa(int num, char* str, int base)
{
int i = 0;
bool isNegative = false;
/* Handle 0 explicitely, otherwise empty string is printed for 0 */
if (num == 0)
{
str[i++] = '0';
str[i] = '\0';
return str;
}
// In standard itoa(), negative numbers are handled only with
// base 10. Otherwise numbers are considered unsigned.
if (num < 0 && base == 10)
{
isNegative = true;
num = -num;
}
// Process individual digits
while (num != 0)
{
int rem = num % base;
str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
num = num/base;
}
// If number is negative, append '-'
if (isNegative)
str[i++] = '-';
str[i] = '\0'; // Append string terminator
// Reverse the string
reverse(str, i);
return str;
}
char* timeConversion(char* s) {
/*
* Write your code here.
*/
char *result = (char*)calloc(8,sizeof(char)) ;
char *ampm = (char*)calloc(2,sizeof(char)) ;
char *hh = (char*)calloc(2,sizeof(char)) ;
int a = 0, b = 0 ,c = 0,i;
long int dec = 0;
int len = strlen(s);
// substring hh:mm:ssAM
while ( c < 2) // 2 : LENGTH
{
ampm[c] = s[9+c-1]; // 9 : position
hh[c] = s[1+c-1]; // 1 : position
c++ ;
}
// string to int
//len = strlen(ampm);
for(i = 0; i < 2 ; i++)
{
dec = dec * 10 + (hh[i] - '0');
}
b = strcmp(ampm,"PM");
a = strcmp(ampm,"AM");
printf("%d\n",a);
printf("%d\n",b);
// processing
if (!strcmp(ampm,"AM") && dec==12) dec = 0;
if (!strcmp(ampm,"PM") && dec!=12) dec += 12;
//if (strcmp(s[9],'A') && dec==12) dec = 0;
//if (strcmp(s[9],'P') && dec!=12) dec += 12;
// convert int back to string
char* hhh = itoa(dec, hh, 10);
//dec = atol(hh);
// hh = itoa(dec,10);
// snprintf(result,9,"%d", dec);
//printf("%s\n",hh);
c = 0;
char* sub;
while (c < 9)
{
sub[c] = s[3+c-1];
c++ ;
}
strcat(result,hhh);
strcat(result,sub);
return result;
}
int main()
{
char *s = "07:05:45PM";
char* result = timeConversion(s);
printf("%s\n", result);
return 0;
}
Like the commenters mentioned, it seems like you are missing the NULL-termination, e.g.:
char *ampm = (char*)calloc(2,sizeof(char)) ;
Two characters ('am'/'pm') plus the NULL-Termination would be 3 characters, not 2.
You have to make sure that all your strings have a size of len + 1 and are properly '\0' terminated.
There are 4 issues in your code.
You are not allocating memory to NULL char for apmp
char *ampm = (char*)calloc(3,sizeof(char)) ;
You are receiving double pointer for swap function and passing char value
void swap(char **str1_ptr, char **str2_ptr)
should be
void swap(char *str1_ptr, char *str2_ptr)
and you call swap function like below
swap((str+start), (str+end));
You are not allocating memory to sub pointer
char* sub = malloc (9 * sizeof(char));
You are not deallocating memory for hh, sub and ampm.
free (hh); free(ampm); free(sub);
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char * compress(char *input, int size){
char *inputa;
char compressedString[100];
inputa = (char*)malloc(sizeof(size));
snprintf (inputa, size, "%s", input);
int i = 0;
int x;
int counter;
while(i < size){
counter = 1;
x = i;
while (inputa[x] == inputa[x + 1] && (x+1) < size){
x++;
counter++;
}
if (i != x){
i = x;
}else{
i++;
}
}
return inputa;
}
main(){
char ez[] = "blaablaaa";
printf("%s \n", compress(ez, sizeof(ez)));
printf("%s", ez);
return 0;
}
So, I am trying to make this function that compresses consecutive characters (eg. "blaablaaa" to "bla2bla3"). My thought process is to put the inputa[x] on the compressed array and next to it the counter, but I can't seem to make it to work.
Lets take a look at these two lines:
inputa = (char*)malloc(sizeof(size));
snprintf (inputa, size, "%s", input);
size has type int, so sizeof(size) is the size of an integer, which is probably 4.
You used malloc to allocate 4 bytes.
Then you use snprintf to try to copy all of your input (blaablaaa, 10-bytes long) into a buffer that is only 4 bytes long.
10 bytes won't fit into a 4 byte buffer.
I'm not sure what you're trying to do there, but it is not correct.
1) Your allocated buffer was too short:
inputa = (char*)malloc(sizeof(size));
It allocates only 4 bytes.
You needed
inputa = (char*)malloc(sizeof(char)*size + 1 ));
2) You forgot to release the allocated memory.
3) The algorithm itself needed the improvements. Comments in the code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
/* reverse: reverse string s in place */
void reverse(char s[])
{
int i, j;
char c;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/* itoa is not a standard function */
/* itoa: convert n to characters in s */
void itoa1(int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
char * compress(char *input, int size){
int i = 0;
int r; // number of repetitions
char add[2]; // current character buffer
char rep[32]; // repetitions buffer
char c; // current character
char *compr = (char* )malloc(sizeof(char)*size + 1); // memory for the compressed string
compr[0] = 0; // terminate the buffer
add[1] = 0; // terminate the buffer
while(i < size){
c = add[0] = input[i]; // get a character
strcat(compr,add); // add to compr
r = 1; // default number of repetitions is one
while(1) // count and add to the string
{
if(c == input[i+1] )
{ // find how many characters follows c
r++; // number of repetition
i++; // moving along the input buffer
}
else
{
// check the r for number of repetitions
if( r > 1)
{
// there were repetitions:
// char * itoa ( int value, char * str, int base );
itoa1(r,rep); // get the number
strcat(compr,rep); // add repetition number to the compressed string
}
i++;// advance to the next character
break;
} // else
}// while
} //while
return compr;
}
int main(void){
char sg7[] = "BLaaaBBLLaaaaXXXaaY";
char ez[] = "blaablaaa";
char *ptr;
printf("%s \n", ptr = compress(sg7, strlen(sg7) ) );
printf("%s \n", sg7);
free(ptr);
printf("\n");
printf("%s \n", ptr = compress(ez, strlen(ez)));
printf("%s \n", ez);
free(ptr);
return 0;
}
Output:
BLa3B2L2a4X3a2Y
BLaaaBBLLaaaaXXXaaY
bla2bla3
blaablaaa
I hope it helps.
I'm trying to convert an integer to a char* pointer so I can properly send the argument into another function. Is there anyway to do this without atoi?
int number=2123, number2= 1233;
char* arg[];
arg[0] = number;
arg[1] = number2;
**Sorry for not making things clear so basically I want the arg[0] to equal the string rep of the number, so that i can send it into a function like this: converted(char* arg);
i would change the parameter data type but it has to be that pointer to send in.
If you assume that a pointer is always at least the same size as an integer (are there any exceptions to this?) you can safely convert integers to pointers and back with these macros:
#define INT2POINTER(a) ((char*)(intptr_t)(a))
#define POINTER2INT(a) ((int)(intptr_t)(a))
Or if that other function isn't your function, but a function that wants the integers as string you could use asprintf() like this:
asprintf(&arg[0],"%d",number);
asprintf(&arg[1],"%d",number2);
But asprintf is not posix standard so it might not be available on all systems. You could use sprintf() (or snprintf() so be on the safe side) instead, but then you need to calculate the string length first.
to convert an integer to a char* pointer so I can properly send the argument into another function.
Create a string representation of the number by calling a helper function with a char array via a compound literal to convert the number. The string will be valid for the function and to the end of the block of code. Adequate sizing of the string is important - leave that for a separate exercise. Code here uses 41, enough for 128 bit int. No need for a memory management via malloc()/free() for such a small buffer.
char *my_itoa(char *dest, int i) {
sprintf(dest, "%d", i);
return dest;
}
#define ITOA(n) my_itoa((char [41]) { 0 }, (n) )
int main(void) {
int number=2123, number2= 1233;
printf("<%s> <%s>\n", ITOA(number), ITOA(number2));
printf("<%s> <%s> <%s>\n", ITOA(INT_MIN), ITOA(0), ITOA(INT_MAX));
}
Output
<2123> <1233>
<-2147483648> <0> <2147483647>
Here is the function you"re looking for:
char *int_to_char(int nb)
{
int div;
char *str;
int i;
int size;
int sign;
i = -1;
sign = 1;
size = get_int_lenght(nb);
if (!(str = malloc(sizeof(char) * (size + 1))))
return (NULL);
if (nb < 0)
{
sign *= -1;
nb *= -1;
}
if (nb == 0)
{
str[++i] = '0';
str[i + 1] = 0;
return (str);
}
while (nb > 0)
{
str[++i] = (nb % 10) + '0';
nb /= 10;
}
if (sign < 0)
str[++i] = '-';
str[i + 1] = 0;
return (my_revstr(str));
}
With revstr function:
char *my_revstr(char *str)
{
int i;
int j;
char tmp;
i = -1;
j = strlen(str);
while (++i < j)
{
tmp = str[i];
str[i] = str[--j];
str[j] = tmp;
}
return (str);
}
And get_int_lenght function:
int get_int_lenght(int nb)
{
int size;
size = 0;
if (nb <= 0)
{
size++;
nb *= -1;
}
while (nb > 0)
{
size++;
nb /= 10;
}
return (size);
}
Suppose that we have a string "11222222345646". So how to print out subsequence 222222 in C.
I have a function here, but I think something incorrect. Can someone correct it for me?
int *longestsubstring(int a[], int n, int *length)
{
int location = 0;
length = 0;
int i, j;
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
{
if (a[i] != a[j])
{
if (i - j >= *length)
{
*length = i - j;
location = j;
}
j = i;
}
}
return &a[location];
}
Sorry,I don't really understand your question.
I just have a little code,and it can print the longest sub string,hope it can help.
/*breif : print the longest sub string*/
void printLongestSubString(const char * str,int length)
{
if(length <= 0)
return;
int i ;
int num1 = 0,num2 = 0;
int location = 0;
for(i = 0; i< length - 1; ++i)
{
if(str[i] == str[i+1])
++num2;//count the sub string ,may be not the longest,but we should try.
else
{
if(num2 >num1)//I use num1 store the sum longest of current sub string.
{ num1 = num2;location = i - num2;}
else
;//do nothing for short sub string.
num2 = 0;
}
}
for(i = location;str[i]== str[num1];++i)
printf("%c",str[i]);
printf("\n");
}
int main()
{
char * str = "1122222234566";
printLongestSubString(str,13);
return 0;
}
From your code it appears you want to return the longest sub-sequence (sub-string). Since I'm relearning C I thought I would give it a shot.
I've used strndup to extract the substring. I'm not sure how portable it is but I found an implementation if needed, just click on the link. It will allocate memory to store the new cstring so you have to remember to free the memory once finished with the substring. Following your argument list, the length of the sub-string is returned as the third argument of the extraction routine.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len);
int main()
{
char str[] = "11222234555555564666666";
size_t substr_len = 0;
char *substr = extract_longest_subsequence(str, sizeof(str), &substr_len);
if (!substr)
{
printf("Error: NULL sub-string returned\n");
return 1;
}
printf("original string: %s, length: %zu\n", str, sizeof(str)-1);
printf("Longest sub-string: %s, length: %zu\n", substr, substr_len);
/* Have to remember to free the memory allocated by strndup */
free(substr);
return 0;
}
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len)
{
if (str == NULL || str_len < 1 || longest_len == NULL)
return NULL;
size_t longest_start = 0;
*longest_len = 0;
size_t curr_len = 1;
size_t i = 0;
for (i = 1; i < str_len; ++i)
{
if (str[i-1] == str[i])
{
++curr_len;
}
else
{
if (curr_len > *longest_len)
{
longest_start = i - curr_len;
*longest_len = curr_len;
}
curr_len = 1;
}
}
/* strndup allocates memory for storing the substring */
return strndup(str + longest_start, *longest_len);
}
It looks like in your loop that j is supposed to be storing where the current "substring" starts, and i is the index of the character that you are currently looking at. In that case, you want to change
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
to
for (i = 0, j = 0; i <= n-1; i++)
That way, you are using i to store which character you're looking at, and the j = i line will "reset" which string of characters you are checking the length of.
Also, a few other things:
1) length = 0 should be *length = 0. You probably don't actually want to set the pointer to point to address 0x0.
2) That last line would return where your "largest substring" starts, but it doesn't truncate where the characters start to change (i.e. the resulting string isn't necessarily *length long). It can be intentional depending on use case, but figured I'd mention it in case it saves some grief.