I am trying to implement this simple encryption method for a a list of numbers, the encryption is like this:
we add the 1st element of the list before every element of the entire list of numbers,
if we have:
char array = "356307042441013"
the first number is 3, that means we need to add it before every element of the list of numbers:
'33 35 36 33 30 37 30 34 32 34 34 31 30 31 33'
char result= "333536333037303432343431303133"
is there any function in C that will make the implementation easier ? because I tried doing it with shifting but couldn't get that result.
You can do following:
Step I: Allocate memory of double the size of input and + 1 to accommodate the null character to the result string.
Step II: Iterate through the input string and, in every iteration, first copy the input[0] character to current location of result string and, in very next location of result string, copy the current processing character of input string.
Step III: Once the loop exits, add null character at the end of result string.
[Take special care of empty string because it will have nothing to encrypt]
Implementation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * encryption (const char * input) {
if ((!input) || (*input == '\0')) {
return NULL;
}
size_t len = strlen (input);
char * temp = malloc ((len * 2) + 1);
if (!temp) {
printf ("Failed to allocate memory\n");
exit (EXIT_FAILURE);
}
size_t i = 0, j = 0;
for (; input[j]; ++j) {
temp[i++] = input[0];
temp[i++] = input[j];
}
temp[i] = '\0';
return temp;
}
int main (void) {
char array[] = "356307042441013";
char * result = encryption (array);
if (result) {
printf ("result : %s\n", result);
// Free the dynamically allocated memory once done with it
free (result);
}
return 0;
}
Output:
# ./a.out
result : 333536333037303432343431303133
A cleaner, more concise solution:
#include <stdio.h>
#include <string.h>
int main()
{
char foo[] = "356307042441013";
char bar[2 * sizeof(foo) - 1];
char *src = foo, *dest = bar;
while (*src) {
*dest++ = foo[0];
*dest++ = *src++;
}
*dest = *src;
printf("foo=%s\n",foo);
printf("bar=%s\n",bar);
return 0;
}
It is better to use foo[] rather than hard-coding the length, because what if you want to change the string. If you use [] (empty brackets) the compiler will allocate exactly how many bytes you need (including the terminating null). Similarly, for bar we base the size on the size of foo by doubling it and subtracting 1 (since the terminating null does not need to be doubled).
I found a way to solve this:
int main() {
char foo[16] = "356307042441013";
char bar[2*16-1];
for (int i = 0; i < 16; i++) {
bar[2*i] = foo[i];
if (i != 16 - 1)
bar[2*i + 1] = foo[0];
}
char res[32]= "3";
strcat(res,bar);
res[30] = '\0';
printf("bar=%s\r\n",bar);
printf("begin=%s\r\n",res);
return 0;
}
Related
I am really new to C and in my first half year at university. This is my first questio on StackOverflow.
My task is to program it so every string stored in numbers is being converted into a decimal, without changing anything outside the main function.
I am now trying for the past 4 hours to solve this problem, where I want to iterate trough every char in the string I am currently to then, based on there position in comparison to the length to convert it into a decimal.
My only question here is to someone help me to understand how I can get the string length without using strlen() due to the fact I can't add #include <string.h>
This is what I got so far (getting the length of the array to iterate through every index):
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
int length = sizeof(numbers);
for ( int i = 0; i < length; i++ ){
//how do i get the string size without strlen() D:
}
return 0;
}
In C, strings are really just char arrays with a special terminator character to mark the end of the string. So, say you have something like:
char *str = "hello";
This is essentially equivalent to this:
char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};
Notice that \0 character at the end of the array? This is the special terminator character that C places at the end of strings. Functions like strlen() pretty much iterate through the char array looking for the first occurrence of the \0 character and then stopping.
So, you can make your own version of strlen(), say my_strlen() like this:
int my_strlen(char *str)
{
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
Then within your for loop, you can just call this function. Also, note that your calculation of the size of the numbers array:
int length = sizeof(numbers);
will not give you the number of elements in the array. That code gives you the size (in bytes) or numbers which is an array of char pointers. If you want to get the number of elements, you have to divide that size by the size (in bytes) of a single element (i.e., a char pointer). So, something like this would work:
int length = sizeof(numbers) / sizeof(numbers[0]);
Your final code can look something like this:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int my_strlen(char *str) {
/* Initialize len to 0 */
int len = 0;
/* Iterate through str, increment len, and stop when we reach '\0' */
while(str[len] != '\0')
len++;
/* Return the len */
return len;
}
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
// Add here..
// Notice the change here
int length = sizeof(numbers) / sizeof(numbers[0]);
for(int i = 0; i < length; i++ ){
int str_len = my_strlen(numbers[i]);
// Do what you need with str_len
}
return 0;
}
This project can be done without computing the length of the strings. How? In C, all strings are nul-terminated containing the nul-character '\0' (with ASCII value 0) after the last character that makes up the string. When you need to iterate over a string, you just loop until the character values is 0 (e.g. the nul-character)
This is how all string function know when to stop reading characters. Since you have an array-of-pointers that contains your strings, you just need to loop over each pointer and for each pointer, loop over each character until the nul-character is found.
Putting it altogether, (and noting you don't need math.h), you can do:
#include <stdio.h>
#include <math.h> // Kompilieren mit -lm : gcc -Wall -std=c11 dateiname.c -lm
int main() {
char* numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"};
int nnumbers = sizeof numbers / sizeof *numbers; /* no. of elements */
for (int i = 0; i < nnumbers; i++) {
long long unsigned number = 0;
/* you don't care about the length, strings are nul-terminated,
* just loop until \0 is found.
*/
for (int j = 0; numbers[i][j]; j++) {
number <<= 1; /* shift left */
number += numbers[i][j] == '1' ? 1 : 0; /* add bit */
}
printf ("%s = %llu\n", numbers[i], number); /* output result */
}
return 0;
}
(note: you must use a 64-bit type to hold the converted values as "1010110011010101111101111010101110110" requires a minimum of 38 bits to represent)
Example Use/Output
Simple example output converting each string to a numeric value:
$ ./bin/binstr2num
01001001 = 73
00101010 = 42
010100111001 = 1337
011111110100101010010111 = 8342167
0001010110011010101111101111010101110110 = 92790519158
01011100110000001101 = 379917
#include <stdio.h>
int main(){
char arr[20]="Hello";
int count=0;
while(arr[count]!='\0'){
count++;
}
printf("%d",count);
return 0;
}
Look at this small code, you will understand. In C a string ended with a NULL character. We can use that advantage.
There are a few ways to do it. IMO, a simple, reasonable way to implement strlen is:
size_t string_length(const char *s) { return strchr(s, '\0') - s; }
but if you're not allowed to use strlen then you're probably not allowed to use strchr either. So you just have to count. The most idiomatic way to do that is probably a bit obscure for a complete beginner, so here is a more verbose method.
Note that your computation of the number of elements in the array is invalid, and has been corrected below.
#include <stdio.h>
int
length(const char *s)
{
int len = 0;
while( *s++ ){
len += 1;
}
return len;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
int count = sizeof numbers / sizeof *numbers; /* Number of entries */
for( int i = 0; i < count; i++ ){
printf(" length of %s is %d\n", numbers[i], length(numbers[i]));
}
return 0;
}
It's pretty subjective, but IMO a more idiomatic way to write this is:
#include <stdio.h>
int
length(const char *e)
{
const char *s = e;
while( *e++ )
;
return e - s - 1;
}
int
main(void)
{
char *numbers[] = {
"01001001",
"00101010",
"010100111001",
"011111110100101010010111",
"0001010110011010101111101111010101110110",
"01011100110000001101"
};
char **e = numbers + sizeof numbers / sizeof *numbers;
for( char **t = numbers; t < e; t++ ){
printf(" length of %s is %d\n", *t, length(*t));
}
return 0;
}
I have a char string containing hexadecimal characters (without 0x or \x):
char *A = "0a0b0c";
from which I want to obtain
const char *B = "\x0a\x0b\x0c";
Is there an efficient way to do this? Thanks!
EDIT: To be clear, I want the resultant string to contain the 3 characters \x0a, \x0b, \x0c, not a 12 character string that says "\x0a\x0b\x0c" where the \ and x are read as individual characters.
This is what I have tried:
const char *B[12];
for (j = 0; j < 4; ++j) {
B[4 * j + 0] = '\\';
B[4 * j + 1] = 'x';
B[4 * j + 2] = A[2 * j];
B[4 * j + 3] = A[2 * j + 1];
};
B[12] = '\0';
which gives me a 12 character string "\x0a\x0b\x0c", but I want B to be as if it was assigned thus:
const char *B = "\x0a\x0b\x0c";
There are multiple confusions in your code:
the input string has 6 characters and a null terminator
the output string should be defined as const char B[3]; or possibly const char B[4]; if you intend to set a null terminator after the 3 converted bytes.
the definition const char *B[12]; in your code defines an array of 12 pointers to strings, which is a very different beast.
The for is fine, but it does not do what you want at all. You want to convert the hexadecimal encoded values to byte values, not insert extra \ and x characters.
the trailing ; after the } is useless
you set a null terminator at B[12], which is beyond the end of B.
Here is a corrected version using sscanf:
const char *A = "0a0b0c";
const char B[4] = { 0 };
for (j = 0; j < 3; j++) {
sscanf(&A[j * 2], "%2hhx", (unsigned char *)&B[j]);
}
The conversion format %2hhx means convert at most the first 2 bytes at A[j * 2] as an unsigned integer encoded in hexadecimal and store the resulting value into the unsigned char at B[j]. The cast is only necessary to avoid a compiler warning.
You can write a function that would sprintf the desired into a string, and then concat that with the destination string.
Something along these lines...
#include <stdio.h>
#include <string.h>
void createB (char B[10], const char *start)
{
char temp[10];
sprintf(temp, "\\x%c%c", start[0], start[1]);
strcat(B, temp);
}
int main ()
{
char A[] = "0a0b0c";
char B[10] = {'\0'};
for (int i=0; A[i] != '\0'; i = i+2)
{
createB(B, A+i);
}
printf("%s\n", B);
return 0;
}
$ ./main.out
\x0a\x0b\x0c
You can modify that to suit your needs or make it more efficient as you feel.
Please make edits as you please; to make it safer with necessary checks. I have just provided a working logic.
If you simply want to add "\x" before each '0' in the string-literal A with the result in a new string B, a simple and direct loop is all that is required, and storage in B sufficient to handle the addition for "\x" for each '0' in A.
For example:
#include <stdio.h>
#define MAXC 32
int main (void) {
char *A = "0a0b0c",
*pa = A,
B[MAXC],
*pb = B;
do { /* loop over all chars in A */
if (*pa && *pa == '0') { /* if chars remain && char is '0' */
*pb++ = '\\'; /* write '\' to B, adv ptr */
*pb++ = 'x'; /* write 'x' to B, adv ptr */
}
*pb++ = *pa; /* write char from A, adv ptr */
} while (*pa++); /* while chars remain (writes nul-termining char) */
puts (B); /* output result */
}
You cannot simply change A to an array with char A[] = 0a0b0c"; and then write back to A as there would be insufficient space in A to handle the character addition. You can always declare A large enough and then shift the characters to the right by two for each addition of "\x", but it makes more sense just to write the results to a new string.
Example Use/Output
$ ./bin/straddescx
\x0a\x0b\x0c
If you need something different, let me know and I'm happy to help further. This is probably one of the more direct ways to handle the addition of the character sequence you want.
#include <stdio.h>
int main(void)
{
char str1[] = "0a0b0c";
char str2[1000];
int i, j;
i = j = 0;
printf("sizeof str1 is %d.\n", sizeof(str1)-1);
for(i = 0; i < sizeof(str1)-1; i += 2)
{
str2[j] = '\\';
str2[j+1] = 'x';
str2[j+2] = str1[i];
str2[j+3] = str1[i+1];
j+=4;
}
str2[j] = '\0';
printf("%s\n", str2);
return 0;
}
I think you can do like this.
Assuming no bad input, assuming 'a' to 'f' are sequentially in order, assuming no uppercase:
// remember to #include <ctype.h>
char *input = "0a0b0c";
char *p = input;
while (*p) {
v = (isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10) * 16;
p++;
v += isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10;
p++;
printf("0x%d", v); // use v
}
While using char A[] = "0a0b0c";, as proposed by kiran, would make it possible to change the string, it wil not yet allow to insert characters. Because that would make the string longer and hence not fit into the available memory. This in turn is a problem, if you cannot create the target string right away with the needed size.
You could know the needed size in advance, if the input is always of the same length and always requires the same number of inserted characters, e.g. if like in your example, the target string is double the size of the input string. For a simple character array definition, you would need to know the size already at compile time.
char A[7] = "0a0b0c"; /* not 6, because size for the termianting \0 is needed */
char B[13] = ""; /* 2*6+1 */
So you can stay with char *A = "0a0b0c"; and make your life easier by setting up memory of appropriate size to serve as target. For that you need to first determine the length of the needed memory, then allocate it.
Determining the size if easy, if you know that it will be twice the input size.
/* inside a function, this does not work as a variable definition */
int iLengthB = 2*length(A);
char* B = malloc(iLengthB+1); /* mind the terminator */
Then loop over A, copying each two characters to B, prepending them with the two characters "\x". I assume that this part is obvious to you. Otherwise please show how you setup the program as described above and make a loop outputting each character from A separatly. Then, after you demonstrated that effort, I can help more.
I have made up a function which returns some chars , all I want to do is to append all those returned chars into one string .
#include <stdio.h>
#include <string.h>
char func(int n);
int main()
{
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
char func(int n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
//EDIT Output for this is 19
char func(n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
You should always specify the type for variables.
Please use something like int n instead of just n.
It's also bad that all of your returns are conditional, it's better to have a return statement that's guaranteed to be executed no matter what *:
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
* Because not returning a value from a function that should return a value is undefined behaviour.
Now that we have that out of the way, let's have a look at your main():
int main() {
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
str[] is not big enough to store all the characters you write to it, resulting in undefined behaviour.
Your loop body is written in a weird way, why are you incrementing p twice?
Here a very simple program that writes 5 characters into str:
#include <stdio.h>
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
int main() {
int i;
// Allocate 6 bytes (5 characters) on the stack
char str[6] = "";
for (i = 0 ; i < 5; i++) {
str[i] = func(i);
}
// Strings *must* be NULL terminated in C
str[5] = 0;
printf("%s",str);
return 0;
}
The size of your str here is "0" (0 using the strlen and 1 using the sizeof operator because it counts the '\0' caracter) so you can not add more element to the str, and if you try, the program will crash. So you have two possibilies here, the first is to declare a fixed table size and the number n will be limited by the size, the second is a dynamic one using mallic. To intialize it to zeros you can just use the memset API.
Well short answer is everything you did would be right if you have in the array enough memory to hold those 5 characters and the \0 if you want to treat it as a string (NUL terminated char array).
"" is a string literal containing only the \0. Length of this string is 0. What about the array? Applying sizeof over it reveals that it is capable of holding one character. (Well it contained \0).
Now with your code you surely did access positions that are beyond the size of the array. This is undefined behavior - mentioned by the C standard.
Solution is to either have an array having size capable of holding the maximum character you would like to store someday. Or you can have a char* to which you can assign address of allocated chunk by using functions like malloc,realloc etc. Benefit of this, you can increase memory as much as you need on runtime depending on the number of characters you want to store.
I just want you to ask what did I do wrong with this code.
I wrote a function that take a char* in parameter, I want to modify it directly without returning smthg, and reverse the string.
#include <iostream>
void reverseString(char *p_string){
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length);
int last_it = 0;
for (int i = 0; i != length; i++){
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
strcpy_s(p_string, length + 1, tmp);
//free(tmp);
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
I'm used to C++ and don't often use C functions like malloc/free/strcpy...
Here, my problem is, when I alloc memory for my temporary char, I called mallec(length) for length = 13 in this case, char = 1 bytes so it should be allocate memory for 13 char is that right?
Problem is allocate more space than need so i need to use '\0' before my strcpy_s if not it breaks.
Did I do a mistake somewhere?
Also, when i call free(tmp), it breaks too and say heap corruption, but I didn't free the memory before that.
Thanks for helping !
I took your original code and added a simple '+1' to the size of the malloc and got a passing result.
Not sure if your exercise is related specifically to the use of malloc, but have you considered doing the reversal directly inside the original string?
For example:
void reverseString(char *p_string){
char* p_end = p_string+strlen(p_string)-1;
char t;
while (p_end > p_string)
{
t = *p_end;
*p_end-- = *p_string;
*p_string++ = t;
}
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
If you are required to use malloc, then you need to ensure that you allocate enough space for string which includes the '\0'
You must use
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
Since strlen doesn't count the \0 character. So this will fail if you don't use length+1:
tmp[last_it] = '\0';
The length of a C string is determined by the terminating
null-character: A C string is as long as the number of characters
between the beginning of the string and the terminating null character
(without including the terminating null character itself).
http://www.cplusplus.com/reference/cstring/strlen/
Btw. C99 support semi dynamic arrays. So could you try this:
char tmp[length+1];
Source:
http://en.wikipedia.org/wiki/Variable-length_array
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; i++)
vals[i] = read_val();
return process(vals, n);
}
Check the below C code:
The memory allocated to tmp should be length+1 as done below and also there are many unnecessary variables which can be avoided.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reverseString(char *p_string){
int i;
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
for (i = 0; i != length; i++){
tmp[i] = p_string[r_it--];
}
tmp[i] = '\0';
strcpy(p_string, tmp);
return;
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
printf("%s",str);
return 0;
}
There is nothing fundamentally wrong with your approach, just some of the details. Since I am not sure how you found out that the sizeof(tmp) is 32, I modified your code to the one below which includes a few printfs and some minor changes:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void reverseString(char *p_string)
{
size_t length = strlen(p_string);
size_t r_it = length - 1;
char* tmp = (char*)malloc(length+1);
int last_it = 0;
size_t i=0;
printf("strlen(p_string) = %d\n", strlen(p_string));
printf("Before: strlen(tmp) = %d\n", strlen(tmp));
for (i = 0; i != length; i++) {
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
printf("After: strlen(tmp) = %d\n", strlen(tmp));
strcpy(p_string, tmp);
free(tmp);
}
int main()
{
char str[] = "StackOverflow";
reverseString(str);
printf("%s\n", str);
return 0;
}
First, I have removed all C++ specific code - you can now compile this with gcc. Running this code yields this output:
sizeof(p_string) = 13
Before: strlen(tmp) = 0
After: strlen(tmp) = 13
wolfrevOkcatS
This is to be expected - strlen basically counts bytes until it hits the \0 character and so the first time we print the size using strlen, it returns 0 since we just allocated the memory. As another poster suggested, we have to allocate 1 extra byte to store the \0 in our new string.
Once the reverse is complete, 13 bytes would have been copied over to this memory and the second strlen returns the expected answer.
I made a small function that fills an allocated block of memory containing every position of a given char within a given string and returns a pointer to the memory block.
The only problem with this function is that there is no way to check the size of the memory block; so I also made a function that counts the occurrence of a given char within a string.
Here is an example of use:
/*count occurences of char within a given string*/
size_t strchroc(const char *str, const char ch)
{
int c = 0;
while(*str) if(*(str++) == ch) c++;
return c;
}
/*build array of positions of given char occurences within a given string*/
int *chrpos(const char *str, const char ch)
{
int *array, *tmp, c = 0, i = 0;
if(!(array = malloc(strlen(str) * sizeof(int)))) return 0x00;
while(str[c])
{
if(str[c] == ch) array[i++] = c;
c++;
}
if(!(tmp = realloc(array, i * sizeof(int)))) return 0x00;
array = tmp;
return array;
}
int main(void)
{
char *str = "foobar foobar"; //'o' occurs at str[1], str[2], str[8], and str[9]
int *array, b = 0, d;
if(!(array = chrpos(str, 'o'))) exit(1); //array[0] = 1, array[1] = 2, array[2] = 8, array[3] = 9
/*
* This is okay since I know that 'o'
* only occures 4 times in str. There
* may however be cases where I do not
* know how many times a given char
* occurs so I figure that out before
* utilizing the contents of array.
* I do this with my function strchroc.
* Below is a sample of how I would
* utilize the data contained within
* array. This simply prints out str
* and on a new line prints the given
* char's location within the str
* array
*/
puts(str);
while(b < (int) strchroc(str, 'o')) //loop once for each 'o'
{
for(d = 0; d < (b == 0 ? array[b] : array[b] - array[b - 1] - 1); d++) putc((int) ' ', stdout);
printf("%d", array[b]);
b++;
}
}
Output:
foobar foobar
12 89
My only concern is that if one of these two functions fail, there is no way for the data to be used correctly. I was thinking about making the number of occurrences of char within the string an argument for chrpos but even then I would still have to call both functions.
I was wondering if anybody had any suggestions for a way to do this so that I only need one function to build the array.
The only way I can think of is by storing the number of char occurrences into array[0] and having array[1] through array[char_occurences] holding the positions of char.
If anybody has a better idea I would greatly appreciate it.
As stated in my comment the first thing is to save up the data anyway, in case you can't shrink the allocated memory :
if (!(tmp = realloc(array, i * sizeof(int))))
return array;
return (tmp); //array = tmp; is useless
If you want to protect a bit more your strchroc function add a if (!str) return 0; at the beginning.
You can change your function so that it also "returns" the number of occurrences found. While we cannot actually return multiple values from a function in C, we can pass a pointer as a parameter and have the function write down a value using that pointer:
int *chrpos(const char *str, char ch, int *found) {
/*
...
*/
*found = i;
return array;
}
Note that you don't need the const modifier for ch.