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.
Related
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;
}
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 am newbie at C so please try to be patient if I am not clear enough.
I have an assignment which I need to make a function that gets a squared char matrix and make a string out of it.
The function should return a pointer to a string eventually,
so that in main I can initialize a string with it and print it in the end.
(also i am restricted to use only pointers inside this function and not regular arrays syntax)
for example the matrix is:
R O M E
G O A L
H E A D
D E A D
and i want to make a sentence like that: "ROME GOAL HEAD DEAD".
I tried to make a for loop which runs only on the matrix rows so I could take each row and copy to a string which I already prepared before (with enough space in it) in the first row I used strcpy() and the other strcat().
Nothing happened.
Sorry for my english, and thanks.
char * makeString(char *smallMat, int rows, char *pStr ) {
int i;
char sentence[(rows * rows) + rows + rows];
pStr = &sentence;
for (i = 0; i < rows; ++i) {
if (i == 0) {
strcpy(sentence, *(smallMat + i));
}
else{
strcat(sentence, ' ' + *(smallMat + i));
}
}
return pStr;
}
As #anonmess pointed out, you cannot use strcpy() etc. for non-0-terminated character sequences. As you said yourself, the task is to use pointers. If you used strcpy() (and if it worked), you would work around the assignment ;)
Here is a full solution that does not use pStr.
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
static char smallMat[4][4] = {
{ 'R', 'O', 'M', 'E' },
{ 'G', 'O', 'A', 'L' },
{ 'H', 'E', 'A', 'D' },
{ 'D', 'E', 'A', 'D' }
};
char* makeString(char* smallMat, int rows) {
int currentRow, currentColumn;
/* space for all characters (rows * rows)
* + one character for each space + terminating '\0'. */
char* sentence = malloc((rows * rows) + rows);
char* p = sentence;
for (currentRow = 0; currentRow < rows; ++currentRow) {
for (currentColumn = 0; currentColumn < rows; ++currentColumn) {
*p++ = *(smallMat + (currentRow * rows) + currentColumn);
}
*p++ = ' ';
}
*--p = '\0'; /* replace the last space with terminating 0,
* so it can be printed. */
return sentence;
}
int main() {
char* output = makeString(smallMat, 4);
printf(output);
free(output);
return 0;
}
The easiest way to go about creating a sentence from your 2D array of SIZE rows and columns of characters is simply to create an array of SIZE * SIZE + SIZE characters to hold the sentence (SIZE * SIZE for each character, plus SIZE - 1 spaces, plus the nul-terminating character)
After declaring an array to hold your sentence, pass both the new array and your 2D array to your makestring() function and loop over each character in the 2D array, adding a space before each word (except for the 1st word) and finally nul-terminate your new array creating a C-string.
You cannot use strcpy (or any other function expecting a C-string) on the row of characters in your 2D array as the rows of characters in your 2D array are not nul-terminated strings. (your 2D array is just that, a 2D array of characters). You must loop over and assign each character to a position within your 1D array.
Putting it altogether, you could write makestring() similar to:
#define SIZE 4
char *makestring (char *str, char (*a)[SIZE])
{
char *p = str; /* a pointer to 1st character in str */
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = a[i][j]; /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to string (for convenient use in-line) */
}
(note: returning a pointer to the beginning of str would allow the function to be used in-line such as: printf ("str: '%s'\n", makestring (str, matrix)); As mentioned, this is just for convenience, you can make the function of type void as you are not allocating and have provided a pointer to an array that will be updated within the function and can be tested back in the caller before use.)
Adding a short test program, you could test your function as follows:
#include <stdio.h>
#define SIZE 4
char *makestring (char *str, char (*a)[SIZE])
{
char *p = str; /* a pointer to 1st character in str */
for (int i = 0; i < SIZE; i++) { /* for each row */
if (i) /* if row not 1st */
*p++ = ' '; /* add space */
for (int j = 0; j < SIZE; j++) /* for each char */
*p++ = a[i][j]; /* copy to str */
}
*p = 0; /* nul-terminate string */
return str; /* return pointer to string (for convenient use in-line) */
}
int main (void) {
char matrix[SIZE][SIZE] = { {'R','O','M','E'}, /* square 2D array */
{'G','O','A','L'},
{'H','E','A','D'},
{'D','E','A','D'} },
str[SIZE * SIZE + SIZE] = ""; /* array to hold sentence */
makestring (str, matrix); /* call makestring */
if (*str != 0) /* validate str not empty-string */
printf ("str: '%s'\n", str); /* output string */
}
Example Use/Output
Running the program would produce:
$ ./bin/makestring
str: 'ROME GOAL HEAD DEAD'
(note: single-quotes added around the string to affirmatively show the beginning and end of the string)
Look things over and let me know if you have further questions.
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 am doing a check whether 2 strings are permutations. I sort the strings then compare each character to each other. However, I think my sorting process also changes the original strings (I am very bad with pointers and passing by reference).
Is there a way to check without modifying the original strings?
I also tried using strcpy but I don't really know how to use it.
I tried this in my check() function:
char temp[128];
strcpy(temp, word);
Below is my code. I call the areAnagram function from another function like this:
void check(char *word, struct Entry *en) {
if (areAnagram(en->word, word) == 1) {
//printf("EW:%s W:%s\n", en->word, word);
//For example, this should return something like
// EW:silent W:listen
//But I got
// EW:eilnst W:eilnst
}
}
Structure for Entry:
typedef struct Entry {
char *word;
int len;
struct Entry *next;
} Entry;
Here is the anagram check process:
void quickSort(char *arr, int si, int ei);
int areAnagram(char *str1, char *str2)
{
// Get lenghts of both strings
int n1 = strlen(str1);
int n2 = strlen(str2);
// If lenght of both strings is not same, then they cannot be anagram
if (n1 != n2) {
return 0;
}
// Sort both strings
quickSort (str1, 0, n1 - 1);
quickSort (str2, 0, n2 - 1);
int i;
// Compare sorted strings
for (i = 0; i < n1; i++) {
if (str1[i] != str2[i]) {
return 0;
}
}
return 1;
}
void exchange(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
int partition(char A[], int si, int ei)
{
char x = A[ei];
int i = (si - 1);
int j;
for (j = si; j <= ei - 1; j++) {
if(A[j] <= x) {
i++;
exchange(&A[i], &A[j]);
}
}
exchange (&A[i + 1], &A[ei]);
return (i + 1);
}
void quickSort(char A[], int si, int ei)
{
int pi; /* Partitioning index */
if(si < ei) {
pi = partition(A, si, ei);
quickSort(A, si, pi - 1);
quickSort(A, pi + 1, ei);
}
}
There is a better way of checking whether two strings are anagrams.You can create an array to store the count of each character in first string(increment the ASCII value index in the array). Then traverse second string and decrement the count of each character (ASCII value index in the array). Now check if all elements of array are zero,if yes these are anagrams otherwise not.
int arr[123];
suppose two strings are s1="abba" and s2="baba"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second array arr[97]=0,arr[98]=0;
Now if you traverse the whole array then all elements will be zero.
But if two strings s1="abba" and s2="abac"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second string arr[97]=0,arr[98]=1,arr[99]=-1;
Since all elements of array are not zero so these are not anagrams.
The complexity of above algorithm is O(n).
Hope it helps.
Make a copy using strcpy:
char *copy = malloc(strlen(word) + 1); // can use a temporary buffer, but this allows variable length inputs
strcpy(copy, word);
// use copy as your temporary string
free(copy);
Your title states that you do not want to modify the original string, however your solution uses Quicksort, which modifies the string. Plus, sorting -- even a fast optimized sort -- is an expensive operation and is not needed for the problem you are trying to solve. You could use a lookup table for speed and it would not modify the original string. You simply create a unique number for each letter and sum the values. Equal sums would constitute an anagram.
/* OPTION 1: let the compiler build your table */
static const int A=0x0000001;
static const int B=0x0000002;
static const int C=0x0000004;
/* continue to double for other letters until ... */
static const int Z=0x4000000;
/* OPTION 2: calculate a cheap hash for each letter */
/* Returns 0 for anagram similar to strcmp */
int anagram (const char* word1, const char* word2)
{
/* strings must be equal length */
if (strlen(word1) != strlen(word2))
return -1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
char c;
for (int i = 0 ; word1[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word1[i]);
sum1 += 1 << (c - 'A');
}
for (int i = 0 ; word2[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word2[i]);
sum2 += 1 << (c - 'A');
}
return (int)(sum1 - sum2); /* ignore overflow */
}
The anagram function above is untested and has been written for clarity. You'd need to include the ctype.h to convert the case using toupper().
Finally, you could make a copy of one of the strings, traverse the other string calling strchr() on each character to find the matching character in the copy. If strchr() returns NULL then there is no anagram, otherwise if strchr() returns a valid pointer, use it to modify the copy, e.g. set to char value to 0x01, so that you can sum the chars in the modified copy. In this instance, the strings would be anagrams if the sum of all the chars in the modified copy equal the integer length of the comparison string.