I'm new to C and am having trouble with strings. What I would like to do is create a string like "val1, val2, val3" in a loop.
Currently my code looks something like:
char tagstr[60] = "";
int k;
int n = 5;
for (k=0; k < n; k++) {
char temp[10] = "";
sprintf(temp, ", val%d", k);
strcat(tagstr, temp);
}
But the output of tagstr is ", val#", where # is some long integer value. I'm guessing I'm doing something wrong with pointers here but I've tried everything I can think of without success... any help would be much appreciated.
EDIT: more context, if it helps:
int tagsClosed = strlen(pch1) - strcspn(pch1, ")");
do {
if (curTag.size > 0) {
// problem section
char tagstr[60] = "";
int k;
for (k = 0; k < 5; k++) {
char temp[10] = "";
sprintf(temp, ", val%i", temp, k);
strcat(tagstr, temp);
}
// This prints out something like ", val-890132840" x 5 (same number)
printf ("String is now: %s\n", tagstr);
}
curTag = *(curTag.parent);
tagsClosed--;
} while (tagsClosed > 0);
curTag is a struct:
typedef struct Tag {
char * name;
int size; // number of children
int tagnum;
struct Tag* parent;
} Tag;
The problem is that sprintf(temp, ", val%i", temp, k); adds the value of temp (which is actually the address of the first character in the array) to the string, and doesn't add the value of k to the string at all. This should be sprintf(temp, ", val%i", k);.
You can calculate the amount of space you'd need in advance (including zero terminator):
5+1 + 5+1 + 5+1 + 5+1 + 5+1 + 1 = 31 characters
Also; using strcat is bad (for performance) because you'd be repeatedly searching for the end of the tagstr and then copying the new characters to the end. It would be better to keep track of the current end of tagstr and store then next group of characters directly at the end with no searching, no temporary string and no copying. For example:
void thing(void) {
char tagstr[60];
int pos = 0;
int k;
int n = 5;
for (k=0; k < n; k++) {
pos += sprintf(&tagstr[pos], ", val%d", k);
}
printf ("String is now: %s\n", tagstr);
}
Works for me:
$ gcc -xc - && ./a.out
int main(void) {
char tagstr[60] = "";
int k;
int n = 5;
for (k=0; k < n; k++) {
char temp[10] = "";
sprintf(temp, ", val%d", k);
strcat(tagstr, temp);
}
printf("[%s]\n", tagstr);
}
[, val0, val1, val2, val3, val4]
Unless you're saying the problem is with the initial ", "..
your temp array is too short!
use
char temp[16];
If you decide you don't want the leading comma and blank, you can use a simple variation on the code you showed:
#include <stdio.h>
#include <string.h>
int main(void)
{
char tagstr[60] = "";
const char *pad = "";
int k;
int n = 5;
for (k = 0; k < n; k++)
{
char temp[10] = "";
snprintf(temp, sizeof(temp), "%sval%d", pad, k);
strcat(tagstr, temp);
pad = ", ";
}
printf("tagstr <<%s>>\n", tagstr);
return 0;
}
The output from the program was:
tagstr <<val0, val1, val2, val3, val4>>
However, your code works correctly for me, albeit with the leading comma and blank.
temp isn't long enough to hold the result of your sprintf. This is exactly why you should use snprintf, strncat and other variants of the string functions that take a size parameter, whenever you can.
Related
I want to repeat a string - for example hello - for a specific number of imes - for example 3 times -, but it doesnt work :) The example should look like this: hellohellohello, but I get no output or i get HHHHHHHHHHH...
here is my code:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
int z = length;
char *ausgabe = calloc((length*(count+1)), sizeof(char));
for(int i = 0; i<=((int) count);i++){
for(int j =0; j< length; j++){
ausgabe[i+j+z] = src[j];
}
z=z*2;
}
//printf("%s\n", ausgabe);
return(ausgabe);
}
If i remove the 'z' in the brackets of 'ausgabe', i get the output HHHHHHHH%, with the z I just get no output. Could bdy pls help me change this behavoiur - and more important, understant why it does that?
As you are always referring *src, which is fixed to the first letter of src,
the result looks like repeating it. Would you please try instead:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
char *ausgabe = calloc(length * count + 1, sizeof(char));
for (int i = 0; i < count; i++) {
for (int j = 0; j < length; j++) {
ausgabe[i * length + j] = src[j];
}
}
//printf("%s\n", ausgabe);
return ausgabe;
}
The strcat function is your friend. We can calloc a buffer long enough for n source strings, plus one for the null terminator, and then just concatenate the source string onto that buffer n times.
char *repeat_string(int n, const char *s) {
int len = strlen(s) * n + 1;
char *result = calloc(len, 1);
if (!result) return NULL;
for (int i = 0; i < n; i++) {
strcat(result, s);
}
return result;
}
I currently try to combine 2 arrays without using strncat. The following code doesnt work and the problem lies in one of the for loops. I guess that some of these boundaries are wrong, but I'm not capable of finding the mistake:
#include <stdio.h>
int main() {
char text1[] = {"Hello"};
char text2[] = {", how are you?"};
char result[100];
int count1 = strlen(text1);
int count2 = strlen(text2);
printf("%d\n", count1);
printf("%d\n", count2);
for(int i = 0; i<count1; i++) {
result[i] = text1[i];
}
for(int k = 0; k<count2; k++) {
result[k+1+count1] = text2[k];
}
for(int j = 0; j<count1+count2; j++) {
printf(" %s", result[j]);
}
return 0;
}
#include <stdio.h>
#include <string.h>
int main() {
char text1[] = "Hello"; //correct way to initialize string
char text2[] = ", how are you?";
char result[100];
int count1 = strlen(text1);
int count2 = strlen(text2);
printf("%d\n", count1);
printf("%d\n", count2);
for(int i = 0; i<count1; i++) {
result[i] = text1[i];
}
for(int k = 0; k<count2; k++) {
result[k+count1] = text2[k]; //k + 1 + count1 causes bug
}
result[count1+count2] = '\0' ; //adding NULL char at the end
printf("%s\n" , result) ; //printing the string using %s
return 0;
}
Instead of defining the size of your result array as 100, you should define it equal to the sum of the length of both the input arrays.
Also, the format specifier should be %c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char text1[] = {"Hello"};
char text2[] = {", how are you?"};
int count1 = strlen(text1);
int count2 = strlen(text2);
char *result = malloc(count1 + count2);
printf("%d\n", count1);
printf("%d\n", count2);
for(int i = 0; i<count1; i++) {
result[i] = text1[i];
}
for (int i = 0; i < count2; i++) {
result[count1 + i] = text2[i];
}
for (int i = 0; i < count1 + count2; i++) {
printf("%c", result[i]);
}
return 0;
}
You do it with fewer variables and a lot less code. You've lost track of what is what and 'skip' a space with 'k+1+count1'... Then try to print, in a loop, characters using a %s format specifier. Too complicated!
#include <stdio.h>
int main() {
char result[100], text1[] = "Hello", text2[] = ", how are you?";
int i = 0, j = 0;
while( (result[ i ] = text1[ i ] ) != '\0' )
i++;
while( (result[ i ] = text2[j++] ) != '\0' )
i++;
puts( result );
return 0;
}
The output is as expected.
So this is the code that works and i've explained each line after the code snippet.
#include <stdio.h>
#include<string.h>
int main() {
char text1[] = "Hello";
char text2[] = ", how are you?";
char result[100];
int count1 = strlen(text1);
int count2 = strlen(text2);
printf("%d\n", count1);
printf("%d\n", count2);
for(int i=0 ; i<(count1+count2); i++){
if(i<count1)
{
result[i]= text1[i];
}
else{
result[i]=text2[i-count1];
}
}
for(int j = 0; j<count1+count2; j++) {
printf("%c", result[j]);
}
return 0;
}
In the first loop, you'd see i'm iterating from 0 to the sum of both the string sizes as i'm assuming that there's a single large string instead of two seperate ones.
As you mentioned that count1 is the size of text1 and count2 as the size of text2, so the logic i used here is that as long as the value of i is lesser than the size of the text1, I'm taking the characters from that position in the text and assigning it to the result string, then once i exceeds that, i'm subtracting the count1 value from the i value as it will again take characters from the 0th position from the text2 and assigning it to the result string.
I would also like to also mention that when you initialise a character array as a string, you just use " ", not {" "} and also when you're printing a character array so you use "%c" not "%s" unless you're printing out a string which you do use "%s" and if so, you can remove the looping statement.
Hope this helps!
I have an array of 64 characters, which I need to divide into two parts, the left part of 32 characters and the right part, also 32 characters.
char *IP_M; // 64 characters array
char L[32]; // left part
char R[32]; // right part
The IP_M array is filled in as follow:
char *start_inital_permutation(const char *input) {
char *output = malloc(64 * sizeof(char));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
output[i * 8 + j] = input[IP[i][j] - 1];
}
}
return output;
}
...
IP_M = start_inital_permutation(M);
where M is also a 64 characters string. With the following method I tried to fill the other two array (L, R) by spliting the IP_M.
void fill_LR() {
for (int i = 0; i < 32; i++) {
L[i] = IP_M[i];
R[i] = IP_M[i + 32];
}
}
but when I run the following instructions:
printf("IP_M: %s\n", IP_M);
printf("L: %s\n", L);
printf("R: %s\n", R);
the output is:
IP_M: 1100110000000000110011001111111111110000101010101111000010101010
L: 1100110000000000110011001111111111110000101010101111000010101010
R: 11110000101010101111000010101010
I can't get out of this situation, can someone help me please?
*EDIT: also tried the memcpy() method but it still not work!
Here is the Project if someone want to see it:
https://github.com/ionutbogdandonici/DES_C.git
Strings in C are \0 terminated. So the print function will print the string until it reaches the \0 character.
Assign space for null:
char L[33]; // left part
char R[33]; // right part
Add null terminator:
void fill_LR() {
for (int i = 0; i < 32; i++) {
L[i] = IP_M[i];
R[i] = IP_M[i + 32];
}
L[32] = 0;
R[32] = 0;
}
output[i * 8 + j] = input[IP[i][j] - 1]; is gibberish.
Strings in C are null terminated but you never allocate space for a null terminator anywhere, nor do you null terminate your strings.
Don't use global variables.
I was able to salvage your program like this:
#include <stdio.h>
#include <stdlib.h>
char *start_inital_permutation(const char *input) {
size_t count=0;
char *output = malloc(64 * sizeof(char) + 1);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
output[i * 8 + j] = input[count++];
}
}
output[64] = '\0';
return output;
}
int main()
{
const char input[] = "1100110000000000110011001111111111110000101010101111000010101010";
char *IP_M = start_inital_permutation(input);
char L[32+1]; // left part
char R[32+1]; // right part
for (int i = 0; i < 32; i++) {
L[i] = IP_M[i];
R[i] = IP_M[i + 32];
}
L[32] = '\0';
R[32] = '\0';
printf("IP_M: %s\n", IP_M);
printf("L: %s\n", L);
printf("R: %s\n", R);
}
However, there's no apparent reason why you need to do the middle step with the 64 characters array. You could as well put that one in a union and save the copy (although then the individual left/right strings won't be null terminated). Example:
#include <stdio.h>
#include <stdlib.h>
typedef union
{
char data [64+1];
struct
{
char left[32];
char right[32];
char zero;
};
} ip_t;
ip_t *start_inital_permutation(const char *input) {
size_t count=0;
ip_t* obj = malloc(sizeof(ip_t));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
obj->data[i * 8 + j] = input[count++];
}
}
obj->data[64] = '\0';
return obj;
}
int main()
{
const char input[] = "1100110000000000110011001111111111110000101010101111000010101010";
ip_t *IP_M = start_inital_permutation(input);
printf("IP_M: %s\n", IP_M->data);
printf("L: %.32s\n", IP_M->left);
printf("R: %.32s\n", IP_M->right);
}
Using printf with "%s" assumes the value is a zero terminated string (AKA NULL terminated string).
I.e. a pointer to a sequence of chars, ending with a \0 char.
In your case when printf attempts to print L it prints char, and after the 32 chars that belong to L it continues. It happened to be that R is following L in memory, and so the content of R is also dumped. If the next byte in memory following R was not a 0, you would see even more characters printed. This behavior is dependent on the [possibly atrbitarary] content of your memory.
How to handle the issue (2 ways):
1. You can either increase the size of L and R to 33, and assign the last char to \0:
char L[33]; // left part
char R[33]; // right part
/* ... */
L[32] = '\0';
R[32] = '\0';
2. Or specify to printf the length of the strings (32) like this:
/*----------vvv-------*/
printf("L: %.32s\n", L);
printf("R: %.32s\n", R);
In the later case keep in mind that L and R are not "regular" C strings, which are expected to be zero terminated (at least as far as it concerns common functions like strlen, strcmp etc.).
I am having trouble creating an algorithm that prints all substrings of a given string. This is my implementation now:
#include <stdio.h>
#include <string.h>
// Function to print all sub strings
void subString(char str[], int n)
{
// Pick starting point
for (int len = 1; len <= n; len++)
{
// Pick ending point
for (int i = 0; i <= n - len; i++)
{
// Print characters from current
// starting point to current ending
// point.
int j = i + len - 1;
for (int k = i; k <= j; k++) {
char data[n];
sprintf(data, "%d", str[k]);
printf("%s\n", data);
}
}
}
}
// Driver program to test above function
int main()
{
char str[] = "abc";
subString(str, strlen(str));
return 0;
}
My code is not converting integers to strings. Could someone help me figure out what's wrong?
The logic seems basically fine, but the formatting doesn't make much sense as this prints the digit values for each character and adds a newline for each print call. If you print the characters directly using %c formatting and only print a newline once you've emitted a full substring you'll have a more sensible result.
#include <stdio.h>
#include <string.h>
void subString(char *str, int n)
{
for (int len = 1; len <= n; len++)
{
for (int i = 0; i <= n - len; i++)
{
for (int j = i; j <= i + len - 1; j++)
{
putchar(str[j]);
}
puts("");
}
}
}
int main()
{
char str[] = "abc";
subString(str, strlen(str));
return 0;
}
Output:
a
b
c
ab
bc
abc
A little nitpick: I'd suggest calling this function printSubStrings since it produces a side effect. The name subString doesn't seem to match the contract particularly well.
You can also use the "%.*s" format to extract the substring chunk you want instead of the innermost loop:
void print_substrings(char *str, int n)
{
for (int len = 1; len <= n; len++)
{
for (int i = 0; i <= n - len; i++)
{
printf("%.*s\n", len, str + i);
}
}
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
string str;
cin >> str;
for (int i = 0; i < str.size(); i++) {
for (int len = 1 ; len <= str.size() - i; len++)
{
cout << str.substr(i, len) << endl; // prints substring from starting index i till length len
}
}
return 0;
}
Input:
abcd
Output:
a
ab
abc
abcd
b
bc
bcd
c
cd
d
Hello, let's say I got 2 strings, "Today is a nice day" and "ao". I want to delete the chars of the 2nd string that appear in the 1st one.
This is my issue:
char c[20];
char p[10];
int i,j;
int l1,l2;
printf("Enter a string \n");
scanf("%s",cd);
printf("Enter another string \n");
scanf("%s",car);
len1 = strlen(cd);
len2 = strlen(car);
for (i=0;i<len1;i++){
for (j=0;j<len2;j++){
if (cd[i]==car[j]){
cd[i]="";
}
}
}
What I want is the 1st string to be like "Tdy is nice dy". So I empty the positions where the elements are the same to reposition it later.
Apparently "cd[i]==car[j]" can't be done on C, I got "Invalid conversion from 'const char*' to 'char'.
So i'm pretty much stuck. I'll thank any help.
1) This is a solution matching your algorithm as close as possible.
All what you need is an extra loop and to replace cd[i]=""; which cannot be compiled with cd[i]=0;. The error given by the compiler relates to expression cd[i]=""; cd[i] is a character type and you cannot assign string "" which has a type const char * to char variable. cd[i] is a character "" is a pointer.
The operation cd[i]=0; gives you want you wanted: I empty the positions where the elements are the same to reposition it later. It replaces the unwanted characters with 0.
#include <stdio.h>
#include <string.h>
int main()
{
char cd[] = "Today is a nice day";
char tmp[] = "Today is a nice day";
char car[] = "ao";
int i;
int j;
int k;
int len1 = strlen(cd);
int len2 = strlen(car);
for (i=0;i<len1;i++){
for (j=0;j<len2;j++){
if (cd[i] == car[j]){
cd[i]=0;
}
}
}
k = 0;
for (i=0; i<len1; i++)
{
if(cd[i] == 0)
{
}
else
{
tmp[k] = cd[i];
k++;
}
}
tmp[k] = 0; /* remember to terminate the tmp */
printf("%s\n", tmp);
strcpy(cd,tmp);
printf("%s\n", cd);
return 0;
}
OUTPUT:
Tdy is nice dy
Tdy is nice dy
Alternatively, instead of clearing unwanted character with 0 you could just skip it. This solution is given below:
#include <stdio.h>
#include <string.h>
int main()
{
char cd[] = "Today is a nice day";
char car[] = "ao";
int i;
int j;
int k = 0;
int skip = 0;
int len1 = strlen(cd);
int len2 = strlen(car);
for (i=0; i<len1; i++)
{
for (j=0; j<len2; j++)
{
if (cd[i] == car[j])
{
skip++; // make note that this character is not needed
}
}
if(skip == 0)
{
cd[k] = cd[i]; // copy the character
k++; // increase the position index
}
else
{
// skip the copy of charcter; clear the skip marker
skip = 0;
}
}
cd[k] = 0; // remember to terminate the new ck string!
printf("%s\n", cd);
return 0;
}
OUTPUT:
Tdy is nice dy