static char* test_encrypt_ecb_verbose(char* plain_text_char, char* key_char)
{
uint8_t i,j, buf[64];
uint8_t plain_text[64];
uint8_t* outstr;
outstr = '\0';
memcpy(key,key_char,16) ;
memcpy(plain_text, plain_text_char, 64);
memset(buf, 0, 64);
printf("ECB encrypt verbose:\n\n");
printf("plain text:\n");
for(i = (uint8_t) 0; i < (uint8_t) 4; ++i)
{
phex(plain_text + i * (uint8_t) 16);
}
printf("\n");
printf("key:\n");
phex(key);
printf("\n");
// print the resulting cipher as 4 x 16 byte strings
printf("ciphertext:\n");
for(i = 0; i < 4; ++i)
{
AES128_ECB_encrypt(plain_text + (i*16), key, buf+(i*16));
phex(buf + (i*16));
//function to encrypt
}
printf("decryptedtext:\n");
for (i = 0; i < 4; ++i)
{
AES128_ECB_decrypt(buf + (i * 16), key, plain_text + (i * 16));
phex(plain_text + (i * 16));
//function to decrypt
}
//memcpy(outstr, buf, 64);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 16; j++)
{
outstr[j] = buf + (i * 16);
}
}
In the above code snippet I want to return the output array after encryption as string . Two of my attempts are there at the end. But those aren't correct. Can anyone suggest the correct way?
a char array and a char pointer is not the same thing.
If you need more details you should refer to this post
and it will gives you a solution to get a char * from a char array
char* p = &a[0];
a is your char array and p your destination pointer
then return your pointer. Using your code you can also directly use the char * you get as function parameters
To get it back you should add an additional argument:
static void test_encrypt_ecb_verbose(char* plain_text_char, char* key_char, char** cipher_text_char)
{
... your function ...
*cipher_text_char = malloc(64);
memcpy(*cipher_text_char, buf, 64);
}
From the caller you just do
char* cipher_text_char = NULL;
test_encrypt_ecb_verbose(plain_text_char, key_char, &cipher_text_char);
After test_encrypt_ecb_verbose has been executed, cipher_text_char will point to the memory allocated inside the function.
As an example consider this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* myfunc(char* src, char** dst, int len)
{
*dst = (char*)malloc(len);
memcpy(*dst, src, len);
return *dst;
}
int main(int argc, char* argv[])
{
char* src = "MyFuncTest";
char* dst = NULL;
char* p = NULL;
p = myfunc(src, &dst, strlen(src) + 1);
printf("dst = %s\n", dst);
printf("p = %s\n", p);
return 0;
}
The output is:
dst = MyFuncTest
p = MyFuncTest
Related
I am having trouble with the very last line in my function, where I am stilly learning the basics of C. I have the signature of this function given and am tasked to write a function to concatenate two strings. The commented line outputs the correct result.
#include <stdio.h>
#include <stdlib.h>
// 1) len = dst-len + max_dst_len
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int total_len = len + max_dst_len;
char *new_str = malloc(sizeof(char) * total_len);
for (int i = 0; i < len; i++) {
new_str[i] = dst[i];
}
for (int i = len; i < total_len; i++) {
new_str[i] = src[i - len];
}
new_str[total_len] = '\0';
//printf("%s <--\n", new_str);
dst = *new_str;
return total_len;
}
int main() {
char test1[] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, 10));
printf("%s\n", test1);
}
You should not be adding max_dst_len to the length of dst. max_dst_len is the amount of memory that's already allocated in dst, you need to ensure that the concatenated string doesn't exceed this length.
So you need to subtract len from max_dst_len, and also subtract 1 to allow room for the null byte. This will tell you the maximum number of bytes you can copy from src to the end of dst.
In your main() code, you need to declare test1 to be at least 10 bytes if you pass 10 as the max_dst_len argument. When you omit the size in the array declaration, it sizes the array just big enough to hold the string you use to initialize it. It's best to use sizeof test1 as this argument, to ensure that it's correct for the string you're concatenating to.
#include <stdio.h>
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int len_to_copy = max_dst_len - len - 1;
int i;
for (i = 0; i < len_to_copy && src[i] != '\0'; i++) {
dst[len+i] = src[i];
}
dst[i] = '\0';
//printf("%s <--\n", new_str);
return i + len;
}
int main() {
char test1[6] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, sizeof test1));
printf("%s\n", test1);
}
I'm working on a program that takes command line arguments and splits them in half and then orders them in lexicographical order.
For example:
hello, world!
would turn into:
he
ld!
llo
wor
I have a main method that reads through the arguments, a function that splits the arguments, and finally a function that is supposed to order the halves in lexicographical order. I can't get this to run properly because of argument type errors in the lexicographicalSort method and an incompatible pointer type in the main method. I'm having issues to correct these syntax errors, how exactly would I correct them? Also, is there anything here that would cause logical errors? This is what I have so far:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int splitString(char arg[], int n)
{
int len = strlen(arg);
int len1 = len/2;
int len2 = len - len1; // Compensate for possible odd length
char *s1 = malloc(len1 + 1); // one for the null terminator
memcpy(s1, arg, len1);
s1[len1] = '\0';
char *s2 = malloc(len2 + 1); // one for the null terminator
memcpy(s2, arg + len1, len2);
s2[len2] = '\0';
printf("%s\n", s1);
printf("%s\n", s2);
free(s1);
free(s2);
return 0;
}
int lexicographicalSort(char *arg[], int n)
{
char temp[50];
for(int i = 0; i < n; ++i)
scanf("%s[^\n]",arg[i]);
for(int i = 0; i < n - 1; ++i)
for(int j = i + 1; j < n ; ++j)
{
if(strcmp(arg[i], arg[j]) > 0)
{
strcpy(temp, arg[i]);
strcpy(arg[i], arg[j]);
strcpy(arg[j], temp);
}
}
for(int i = 0; i < n; ++i)
{
puts(arg[i]);
}
return 0;
}
int main(int argc, char *argv[])
{
if (argc > 1)
{
for (int i = 1; i < argc; i++)
{
int j = 1;
int k = strlen(argv[i]);
splitString(argv[i], j);
lexicographicalSort(argv[i], j);
}
}
}
Basic scheme is simple. Make an array of tuples {start_pointer, length}. Do some programming on args to split the args. Fill in the array as appropriate. Make sorting with qsort, or any other sort of your choise.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
char *s = "hello, world! . hello.....";
char *pc;
int i, n, nargs;
struct pp{
char *p;
int l;
};
struct pp args[10], hargs[20];
struct pp *pargs;
int cmp(const void * v0, const void * v1) {
struct pp *pv0 = v0, *pv1 = v1;
return strncmp(pv0->p, pv1->p, pv0->l);
}
int main(void)
{
for(pc = s, i = 0; *pc; ++i){
sscanf(pc, "%*[^ ]%n", &n);
if(n > 0){
args[i].p = pc;
args[i].l = n;
}
for(pc += n, n = 0; isspace(*pc); ++pc);
}
for(nargs = i, i = 0; i < nargs; ++i)
printf("%d arg is: %.*s\n", i, args[i].l, args[i].p);
putchar('\n');
for(i = 0, pargs = hargs; i < nargs; ++i){
if(args[i].l == 1){
pargs->p = args[i].p;
pargs->l = 1;
pargs = pargs + 1;
}else {
pargs->p = args[i].p;
pargs->l = args[i].l / 2;
pargs = pargs + 1;
pargs->p = args[i].p + args[i].l / 2;
pargs->l = args[i].l - args[i].l / 2;
pargs = pargs + 1;
}
}
putchar('\n');
for(nargs = pargs - hargs, i = 0; i < nargs; ++i)
printf("%d arg is: %.*s\n", i, hargs[i].l, hargs[i].p);
qsort(hargs, nargs, sizeof(struct pp), cmp);
putchar('\n');
for(i = 0; i < nargs; ++i)
printf("%d arg is: %.*s\n", i, hargs[i].l, hargs[i].p);
return 0;
}
https://rextester.com/GSH22767
Upon splitting a C string, one needs one extra char to store extra null-terminator. There is one answer that bypasses this by storing the length. For completeness, this is closer to your original intention: allocating enough space to copy the programmes arguments. It probably works slower, but one is free to use the strings elsewhere in the programme.
#include <stdlib.h> /* malloc free EXIT qsort */
#include <stdio.h> /* fprintf */
#include <string.h> /* strlen memcpy */
#include <errno.h> /* errno */
static int strcompare(const void *a, const void *b) {
const char *a_str = *(const char *const*)a, *b_str = *(const char *const*)b;
return strcmp(a_str, b_str);
}
int main(int argc, char **argv) {
char *spacev = 0, **listv = 0;
size_t spacec = 0, listc = 0;
int is_done = 0;
do { /* "Try." */
int i;
char *sv;
size_t j;
/* This requires argc > 1. */
if(argc <= 1) { errno = EDOM; break; }
/* Allocate maximum space. */
for(i = 1; i < argc; i++) spacec += strlen(argv[i]) + 2;
if(!(spacev = malloc(spacec)) || !(listv = malloc(argc * 2))) break;
sv = spacev;
/* Copy and split the arguments. */
for(i = 1; i < argc; i++) {
const char *const word = argv[i];
const size_t word_len = strlen(word),
w0_len = word_len / 2, w1_len = word_len - w0_len;
if(w0_len) {
listv[listc++] = sv;
memcpy(sv, word, w0_len);
sv += w0_len;
*(sv++) = '\0';
}
if(w1_len) {
listv[listc++] = sv;
memcpy(sv, word + w0_len, w1_len);
sv += w1_len;
*(sv++) = '\0';
}
}
/* Sort. */
qsort(listv, listc, sizeof listv, &strcompare);
for(j = 0; j < listc; j++) printf("%s\n", listv[j]);
is_done = 1;
} while(0); if(!is_done) {
perror("split");
} {
free(spacev);
free(listv);
}
return is_done ? EXIT_SUCCESS : EXIT_FAILURE;
}
It is simpler than your original; instead of allocating each string individually, it counts the maximum number of chars needed (plus two for two null terminators) and allocates the block all at once (space.) The pointers to the new list also need allocating, the maximum is 2 * argc. Once you copy and modify the argument list, one has an actual array of strings that one can qsort.
I'm trying to create a program which returns the Longest repeated substring. I've almost got the solution, but for some reason my strcmp gives an error when he is busy to find the LRS. Could someone explain me why there is an error and how I solve this?
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NSTRINGS 4
char* searchLongestRepeatedSubstring(char* string);
char** makeSuffixArray(char* string);
void freeSuffixArray(char** suffixArray);
int cmp(const void*a, const void* b);
/* do not change this code */
int main(void)
{
char* strings[NSTRINGS] = {
"bananas",
"ask not what your country can do for you, but what you can do for your country",
"main",
"" };
char* result;
for (int i = 0; i < NSTRINGS; ++i)
{
result = searchLongestRepeatedSubstring(strings[i]);
if (result != NULL)
{
/* write out LRS */
printf("%s: \"%s\"\n", strings[i], result);
/* free() the result */
free(result);
result = NULL;
}
else
printf("Geen longest repeated substring.\n");
}
return 0;
}
/**
* Finds the LRS from a string using the function makeSuffixArray
*
* #param the given string
* #return the longest repeated substring
*/
char* searchLongestRepeatedSubstring(char* string)
{
char **p;
p = makeSuffixArray(string);
size_t length = strlen(string);
int max_sz = 0;
char max_word;
int curr_sz = 0;
int curr_word;
char* word1;
char* word2;
char s1, s2;
size_t length1;
size_t length2;
for (size_t i = 0; i < length; i++)
{
for (size_t j = i + 1; j < length; j++)
{
word1 = p[i];
word2 = p[j];
length1 = strlen(word1);
length2 = strlen(word1);
for (size_t x = 0; x < length1; x++)
{
s1 = word1[x];
for (size_t y = 0; y < length2; y++)
{
s2 = word2[y];
if (strcmp(s1, s2) == 0) {
curr_sz++;
strcat(curr_word, s1);
x++;
}
else
break;
}
}
if (curr_sz > max_sz) {
max_sz = curr_sz;
curr_sz = 0;
max_word = curr_word;
curr_word = "";
}
else {
curr_sz = 0;
curr_word = "";
}
}
}
return max_word;
}
/**
* Creates the suffix array of the given string
*
* #param the given string
* #return the suffix array
*/
char** makeSuffixArray(char* string)
{
size_t length = strlen(string);
char **p = (char**)malloc(length * sizeof(char*));
for (size_t i = 0; i < strlen(string); i++)
{
p[i] = &string[i];
puts(p[i]);
}
qsort(p, length, sizeof(char*), cmp);
return p;
}
int cmp(const void* a, const void* b)
{
char ** p = (char**)a;
char ** t = (char**)b;
return strcmp(*p, *t);
}
/**
* free() the memory allocated for the suffix array
*
* #param the given suffix array
*/
void freeSuffixArray(char** suffixArray)
{
free(suffixArray);
}
In your function char* searchLongestRepeatedSubstring-
if (strcmp(s1, s2) == 0) {
s1 and s2 are both char variables , and you pass them to strcmp which expects const char * as arguments , therefore, your compiler complaints .
You can compare them like this-
if(s1==s2)
Also this statement in same if block -
strcat(curr_word, s1);
instead you can do this -
size_t len=strlen(curr_word);
curr_word[len]=s1; // make sure curr_word is large enough
curr_word[len+1]='\0';
I need to replace a strings in some text. I found this function here at stackoverflow:
char *replace(const char *s, const char *old, const char *new)
{
char *ret;
int i, count = 0;
size_t newlen = strlen(new);
size_t oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++) {
if (strstr(&s[i], old) == &s[i]) {
count++;
i += oldlen - 1;
}
}
ret = malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s) {
if (strstr(s, old) == s) {
strcpy(&ret[i], new);
i += newlen;
s += oldlen;
} else
ret[i++] = *s++;
}
ret[i] = '\0';
return ret;
}
This function works for me fine for single replacement. But i need to replace a whole array "str2rep" to "replacement". So what i'm trying to do(im just a beginner)
****
#define MAXTEXT 39016
int l;
int j;
char *newsms = NULL;
char text[MAXTEXT];
char *str2rep[] = {":q:",":n:"};
char *replacement[] = {"?","\n"};
strcpy((char *)text,(char *)argv[5]);
l = sizeof(str2rep) / sizeof(*str2rep);
for(j = 0; j < l; j++)
{
newsms = replace(text,(char *)str2rep[j],(char *)replacement[j]);
strcpy(text,newsms);
free(newsms);
}
textlen = strlen(text);
This code even works locally, If I build it from single file... But this is asterisk module, so when this is being executed, asterisk stops with:
* glibc detected * /usr/sbin/asterisk: double free or corruption (!prev): 0x00007fa720006310 *
Issues:
ret = malloc(i + count * (newlen - oldlen)); is too small. Need + 1.
Consider what happens with replace("", "", ""). If your SO ref is this, it is wrong too.
Questionable results mixing signed/unsigned. count is signed. newlen, oldlen are unsigned.
I think the original code works OK, but I do not like using the wrap-around nature of unsigned math when it can be avoided which is what happens when newlen < oldlen.
// i + count * (newlen - oldlen)
size_t newsize = i + 1; // + 1 for above reason
if (newlen > oldlen) newsize += count * (newlen - oldlen);
if (newlen < oldlen) newsize -= count * (oldlen - newlen);
ret = malloc(newsize);
Insure enough space. #hyde Various approaches available here.
// strcpy(text, newsms);
if (strlen(newsms) >= sizeof text) Handle_Error();
strcpy(text, newsms);
Minor
No need for casts
// newsms = replace(text, (char *) str2rep[j], (char *) replacement[j]);
newsms = replace(text, str2rep[j], replacement[j]);
Better to use size_t for i. A pedantic solution would also use size_t count.
// int i;
size_t i;
I will suggest something that to me looks a bit more clear as an alternative, in place of a proper dynamic string implementation. Exception handling is left as an exercise for the reader to add. :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *appendn(char *to, char *from, int length)
{
return strncat(realloc(to, strlen(to) + length + 1), from, length);
}
char *replace(char *string, char *find, char *sub)
{
char *result = calloc(1, 1);
while (1)
{
char *found = strstr(string, find);
if (!found)
break;
result = appendn(result, string, found - string);
result = appendn(result, sub, strlen(sub));
string = found + strlen(find);
}
return appendn(result, string, strlen(string));
}
int main()
{
const char text[] = "some [1] with [2] to [3] with other [2]";
char *find[] = {"[1]", "[2]", "[3]", NULL};
char *sub[] = {"text", "words", "replace"};
char *result, *s;
int i;
result = malloc(sizeof(text));
(void) strcpy(result, text);
for (i = 0; find[i]; i ++)
{
s = replace(result, find[i], sub[i]);
free(result);
result = s;
}
(void) printf("%s\n", result);
free(result);
}
How can I split a const char * string in the fastest possible way.
char *inputStr="abcde";
char buff[500];
I would like to have in buffer the following formatted string, format of which must be:
IN('a','ab','abc','abcd','abcde')
I'm learning C and new to the language. I have no clue where to start on this splitting problem.
I don't think you can do this particularly "fast", it seems like it's quite heavily limited since it needs to iterate over the source string many times.
I'd do something like:
void permute(char *out, const char *in)
{
const size_t in_len = strlen(in);
char *put;
strcpy(out, "IN(");
put = out + 3;
for(i = 1; i < in_len; ++i)
{
if(i > 1)
*put++ = ',';
*put++ = '\'';
memcpy(put, in, i);
put += i;
*put++ = '\'';
}
*put++ = ')';
*put++ = '\0';
}
Note that this doesn't protect against buffer overrun in the output.
You could use strcpy, strcat/strncat and a simple loop:
#include <stdio.h>
#include <string.h>
int main(void) {
char* inputStr = "abcde";
char buff[500];
// start the formatted string:
strcpy(buff,"IN(");
int i, len = strlen(inputStr);
for (i = 0; i < len; ++i) {
strcat(buff, "'");
strncat(buff, inputStr, i + 1);
strcat(buff, "'");
// if it is not last token:
if (i != len - 1)
strcat(buff, ",");
}
// end the formatted string:
strcat(buff,")");
printf("%s", buff);
return 0;
}
outputs the desired IN('a','ab','abc','abcd','abcde')
To give you a start, consider the following code:
char buffer[64];
const char str[] = "abcde";
for (size_t i = 1; i <= strlen(str); ++i)
{
strncpy(buffer, str, i);
buffer[i] = '\0'; /* Make sure string is terminated */
printf("i = %lu, buffer = \"%s\"\n", i, buffer);
}
The above code should print
i = 1, buffer = "a"
i = 2, buffer = "ab"
i = 3, buffer = "abc"
i = 4, buffer = "abcd"
i = 5, buffer = "abcde"
If you are looking for something like this in C++:-
#include <iostream>
#include <string.h>
using namespace std;
int main() {
const char *inputStr = "abcde"; //const to remove warning of deprecated conversion
char buff[500];
int count = 0;
for (int i = 0; i < (int) strlen(inputStr); i++) { //cast it to int to remove
// warning of comparison between signed and unsigned
for (int j = 0; j <= i; j++) {
buff[count++] = inputStr[j];
}
buff[count++] = ',';
}
buff[--count] = '\0';
cout << buff;
return 0;
}
Output - a,ab,abc,abcd,abcde