I have an issue with C strings. I have array char char_array[256] = {0}.
I had fulfilled this array with char elements. When I print these elements printf("%c", char_array[0]);, printf("%c", char_array[1]); and etc, the values are correct. But when I try to print printf("%s", char_array);, it prints nothing...
Also I have function void function(char* char_pointer). I am trying to return data strcpy(char_pointer, char_array). But it returns nothing...
Please, help me, how to return data from function, that later, outside function, I could print printf("%s", char_pointer_from_function)?
UPDATE:
Function:
void unmarshal_packet(char *packet)
{
char packet_size_string [10] = {0};
char unmarshaled_data [2000] = {0};
int counter = 0;
while (packet[counter] != ':' && counter < strlen(packet))
{
packet_size_string[counter] = packet[counter];
counter++;
}
counter = strlen(packet_size_string) + 1;
for (counter; counter < strlen(packet); counter++)
{
if ((packet[counter] != '\r') && (packet[counter] != '\n'))
{
unmarshaled_data[counter - (strlen(packet_size_string) + 1)] = packet[counter];
}
}
// printf("%c", unmarshaled_data[0]);
// printf("%c", unmarshaled_data[1]);
// printf("%c", unmarshaled_data[2]);
// printf("%c", unmarshaled_data[3]);
// printf("%c", unmarshaled_data[4]);
// printf("%c", unmarshaled_data[5]);
// printf("%c", unmarshaled_data[6]);
// printf("%c", unmarshaled_data[7]);
// printf("%c", unmarshaled_data[8]);
// printf("%c", unmarshaled_data[9]);
printf("%s", unmarshaled_data);
unmarshaled_data[counter - (strlen(packet_size_string) + 1)] = '\0';
strcpy(packet, unmarshaled_data);
}
Function call:
strcpy(buffer, " \nWellcome to Yes / No game server! \n");
unmarshal_packet(buffer);
Strings are sequences of non-NULL (ASCII value 0) characters, followed by such a character indicating the end of the string. If, for example, your first character where a NULL, that would represent an empty string, and so nothing would be printed. Not knowing what you put in your array before printing, I cannot say what should be printed.
Related
I did this program to reverse the order of the words in the give string. (And it works)
i.e. Output: sentence first the is This
However I am stuck when it comes to adding another sentence to the array.
For example I need to have an array {"This is the first sentence", "And this is the second"} producing as output: sentence first the is This , second the is this And
int main() {
char str[] = {"This is the first sentence"};
int length = strlen(str);
// Traverse string from end
int i;
for (i = length - 1; i >= 0; i--) {
if (str[i] == ' ') {
// putting the NULL character at the position of space characters for
next iteration.
str[i] = '\0';
// Start from next character
printf("%s ", &(str[i]) + 1);
}
}
// printing the last word
printf("%s", str);
return 0;
}
I am new to C so its not surprising that I got stuck even if the solution is quite easy. Any help would be appreciated! Thanks!
Since you already have the code to print the words of one string in reverse order, I would suggest making that a function which takes a single string as an argument, i.e.:
void print_words_reverse(char * const str) {
// your current code here
}
Then you can call it separately for each string:
char strings[][30] = {
"This is the first sentence",
"And this is the second"
};
for (int i = 0; i < sizeof(strings) / sizeof(*strings); ++i) {
print_words_reverse(strings[i]);
}
Note that since you are modifying the string (by replacing spaces with NUL bytes), the argument needs to be modifiable, which means you are not allowed to call it (in standard C) with a pointer to a string literal, which means you can't simply use const char *strings[] = { "first", "second" }. You could get rid of the ugly constant length (here 30) reserved for every string by making your code not modify the argument string. Or you could have a separate char array for each sentence and then use pointers to those (modifiable) strings.
First, you can try with a two-dimensional array or use an array of pointers.
Secondly, in your approach, you lose the initial value of your string, I don't know how important it is.
This is my fast approach using arrray of pointers.
#include <stdio.h>
#include <string.h>
static void print_word(const char *str)
{
for (int i = 0; str[i] && str[i] != ' '; i++)
printf("%c", str[i]);
putchar(' ');
}
int main(void)
{
int len;
const char *str[] = {"This is the first sentence",
"And this is second", NULL};
for (int i = 0; str[i]; i++) {
for (len = strlen(str[i]); len >= 0; len--) {
if (len == 0)
print_word(&str[i][len]);
else if (str[i][len] == ' ')
print_word(&str[i][len + 1]);
}
putchar('\n');
}
printf("Initial value of array of strings [%s | %s] \n", str[0], str[1]);
return 0;
}
output is:
sentence first the is This
second is this And
Initial value of array of strings [This is the first sentence | And this is second]
I suggest you using memcpy but without altering too much your code this seems to work
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_STRING_LENGTH 100
int main()
{
char *str[] = {"This is the first", "And this is the second sentence"};
const size_t NUM_STRING = sizeof(str)/sizeof(char*);
/*%z used to print size_t variables*/
printf("%zd strings found\n", NUM_STRING);
int length[2];
int i;
for (i=0; i<NUM_STRING; i++)
{
length[i] = strlen(str[i]);
}
printf("length initialized %d %d\n", length[0], length[1]);
// Traverse string from end
int j = 0;
char temp[MAX_STRING_LENGTH];
printf("\n\n");
for (j=0; j<NUM_STRING; j++)
{
/*Make sure the string respect the MAX_STRING_LENGTH limit*/
if (strlen(str[j])>MAX_STRING_LENGTH)
{
printf("ERROR: string %d exceding max string length %d defined in constant "
"MAX_STRING_LENGTH. Exiting from program.\n", j, MAX_STRING_LENGTH);
exit(1);
}
//reset temporary string
memset(temp, '\0', sizeof(temp));
//printf("temp variable reinitialized\n");
for (i = length[j] - 1; i >= 0; i--)
{
temp[i] = str[j][i];
if (str[j][i] == ' ')
{
// putting the NULL character at the position of space characters for next iteration.
temp[i] = '\0';
// Start from next character
printf("%s ", &(temp[i]) + 1);
}
}
// printing the last word
printf("%s ", temp);
}
printf("\n");
return 0;
}
This is for Homework
I have to write a program that asks the user to enter a string, then my program would separate the even and odd values from the entered string. Here is my program.
#include <stdio.h>
#include <string.h>
int main(void) {
char *str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s", &str);
while (&str[i] < 41) {
if (i % 2 == 0) {
odd[j++] = *str[i];
} else {
even[k++] = *str[i];
}
i++;
}
printf("The even string is:%s\n ", even);
printf("The odd string is:%s\n ", odd);
return 0;
}
When I try and compile my program I get two warnings:
For my scanf I get "format '%s' expects arguments of type char but argument has 'char * (*)[41]". I'm not sure what this means but I assume it's because of the array initialization.
On the while loop it gives me the warning that says comparison between pointer and integer. I'm not sure what that means either and I thought it was legal in C to make that comparison.
When I compile the program, I get random characters for both the even and odd string.
Any help would be appreciated!
this declaration is wrong:
char *str[41];
you're declaring 41 uninitialized strings. You want:
char str[41];
then, scanf("%40s" , str);, no & and limit the input size (safety)
then the loop (where your while (str[i]<41) is wrong, it probably ends at once since letters start at 65 (ascii code for "A"). You wanted to test i against 41 but test str[i] against \0 instead, else you get all the garbage after nul-termination char in one of odd or even strings if the string is not exactly 40 bytes long)
while (str[i]) {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
if you want to use a pointer (assignement requirement), just define str as before:
char str[41];
scan the input value on it as indicated above, then point on it:
char *p = str;
And now that you defined a pointer on a buffer, if you're required to use deference instead of index access you can do:
while (*p) { // test end of string termination
if (i % 2 == 0) { // if ((p-str) % 2 == 0) { would allow to get rid of i
odd[j++] = *p;
} else {
even[k++] = *p;
}
p++;
i++;
}
(we have to increase i for the even/odd test, or we would have to test p-str evenness)
aaaand last classical mistake (thanks to last-minute comments), even & odd aren't null terminated so the risk of getting garbage at the end when printing them, you need:
even[k] = odd[j] = '\0';
(as another answer states, check the concept of even & odd, the expected result may be the other way round)
There are multiple problems in your code:
You define an array of pointers char *str[41], not an array of char.
You should pass the array to scanf instead of its address: When passed to a function, an array decays into a pointer to its first element.
You should limit the number of characters read by scanf.
You should iterate until the end of the string, not on all elements of the array, especially with (&str[i] < 41) that compares the address of the ith element with the value 41, which is meaningless. The end of the string is the null terminator which can be tested with (str[i] != '\0').
You should read the characters from str with str[i].
You should null terminate the even and odd arrays.
Here is a modified version:
#include <stdio.h>
int main(void) {
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
if (scanf("%40s", str) != 1)
return 1;
while (str[i] != '\0') {
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = even[k] = '\0';
printf("The even string is: %s\n", even);
printf("The odd string is: %s\n", odd);
return 0;
}
Note that your interpretation of even and odd characters assumes 1-based offsets, ie: the first character is an odd character. This is not consistent with the C approach where an even characters would be interpreted as having en even offset from the beginning of the string, starting at 0.
Many answers all ready point out the original code`s problems.
Below are some ideas to reduce memory usage as the 2 arrays odd[], even[] are not needed.
As the "even" characters are seen, print them out.
As the "odd" characters are seen, move them to the first part of the array.
Alternative print: If code used "%.*s", the array does not need a null character termination.
#include <stdio.h>
#include <string.h>
int main(void) {
char str[41];
printf("Enter a string (40 characters maximum): ");
fflush(stdout);
if (scanf("%40s", str) == 1) {
int i;
printf("The even string is:");
for (i = 0; str[i]; i++) {
if (i % 2 == 0) {
str[i / 2] = str[i]; // copy character to an earlier part of `str[]`
} else {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:%.*s\n ", (i + 1) / 2, str);
}
return 0;
}
or simply
printf("The even string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 != 0) {
putchar(str[i]);
}
}
printf("\n");
printf("The odd string is:");
for (int i = 0; str[i]; i++) {
if (i % 2 == 0) {
putchar(str[i]);
}
}
printf("\n");
here is your solution :)
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[41];
char odd[21];
char even[21];
int i = 0;
int j = 0;
int k = 0;
printf("Enter a string (40 characters maximum): ");
scanf("%s" , str);
while (i < strlen(str))
{
if (i % 2 == 0) {
odd[j++] = str[i];
} else {
even[k++] = str[i];
}
i++;
}
odd[j] = '\0';
even[k] = '\0';
printf("The even string is:%s\n " , even);
printf("The odd string is:%s\n " , odd);
return 0;
}
solved the mistake in the declaration, the scanning string value, condition of the while loop and assignment of element of array. :)
My program aims to print each word in the sentence on a separate line.but I should print it with %s not %c! I already try to implement it but the program does not give me a correct output ! my idea is when you find null character
1- print the word
2- return the index of the temp array to 0 and store a new word
int main () {
char sen[100];
char cpy [100];
printf("Entter a sentence ");
gets(sen);
int len = strlen(sen);
int i = 0;
int k =0;
for (i=0 ; i<len;i++)
{
if (sen[i]!='\0')
{
cpy[k++]+=sen[i];
}
else{
printf("%s\n",cpy);
k=0;}
}
}
You confound null character and space character. Null character \0 stands for "end of string" : the strlen function returns the number of characters before the first \0.
In your forloop, you want to display each word separated by so you have to test with the caracter instead of \0.
Also to correctly display your string you have to end the string with the \0 character. So before the instruction printf you must do cpy[k] = '\0';.
if (sen[i]!='\0') will always be true as pointed by Julien Vernay, you need if (sen[i]!= ' ') instead of if (sen[i]!='\0'), as there are spaces between words, to seprate them.
Also in cpy[k++]+=sen[i]; you are adding sen[i] to cpy[k++] which seams weird, I think what you need is cpy[k++] = sen[i];
Modify your loop as follows...
for (i=0 ; i<len; i++) {
int flag = 0;
while(sen[i] == ' ') i++; // multiple spaces
while(sen[i] != ' ' && sen[i] != '\0') {
cpy[k++] = sen[i];
flag = 1;
i++;
}
if(flag) {
cpy[k] = '\0';
printf("%s\n",cpy);
k=0;
}
}
You can have to not bother with doing a copy - all you need to do is essentially replace spaces with new lines. So here is the code to do this:
#include <stdio.h>
int main()
{
char sen[100];
bool last_char_space = true;
printf("Please enter a sentence: ");
fflush(stdout);
fgets(sen, 100, stdin);;
for (int loop = 0; sen[loop]; ++loop) { // send[loop] is true until end of string - saves repeatedly calling strlen
if (send[loop] == ' ') { // A space
if (last_char_space) { // Last character not a space, put new line
fputc('\n', stdout);
}
last_char_space = true; // Record the fact that we are between words
} else {
fputc(sen[loop], stdout); // Not a space - print it
last_char_space = false; // We are working on a word
}
}
return 0;
}
So I'm given a string as such:
Hello6World66ABC
Where I'm told to replace single instances of the character '6' to be two asteric characters "**"
And multiple instances of 6's to be two of these characters "^^" (Any combinations of the number 6 in a row would qualify.
I'm attempting to do this by passing through each character in a char *,then if I find the 6 character, I check if the next character is a 6, if not we have the first case, otherwise we have the second case (Multiple 6's).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char * str;
int i;
str = malloc(17);
strcpy(str,"Hello6World66ABC");
for(i=0; i < strlen(str); i++) {
if(str[i] == '6') {
if(str[i+1] != '6') {
char * token = strtok(str,"6");
strcpy(str,token);
strcat(str,"**");
printf("String is now %s\n",str);
token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */
printf("Rest of the string is %s\n",token);
str = (char *) realloc(str,strlen(str) + strlen(token) + 1);
strcat(str,token);
printf("String is now %s\n",str);
/* should be Hello**World66ABC */
}
else {
/*if the next characters are also (multiple ones in a row) 6's, replace it with two ^^ characters*/
char * token = strtok(str,"6");
token = strtok(NULL,"6");
printf("TOKEN IS %s\n",token);
strcpy(str,token);
strcat(str,"^^");
token = strtok(NULL,""); /*get the rest of the string*/ /* should be World66ABC */
printf("Rest of the string is %s\n",token);
str = (char *) realloc(str,strlen(str) + strlen(token) + 1);
strcat(str,token);
printf("String is now %s\n",str);
}
}
}
free(str);
return 0;
}
By the string given, My expected final string should be:
Hello**World^^ABC
However, my strtok calls don't work the way I intended.
In the second if statement, where I check if (str[i+1] != '6'), I'm checking if there is only a single 6, there is.
Then I call strtok and print everything before it:
it prints: Hello**
Which is correct
I strcat the new characters on to it which works, however, on my second strtok call, to get the rest of the string, it just doesn't work.
It instead prints:
"Rest of the string is *"
So clearly it's not getting the rest of the string, even though I set the delimiter to be an empty string.
I tried to change the delimiter to be other characters, but each result in the same output. I'm also reallocating because the string gets longer, in the first case. Also the else statement seems to never run, even though I clearly have a case where there are multiple 6's.
I'm not sure where I've gone wrong here, any ideas?
This is untested, but it shows the general idea.
strcpy(str,"Hello6World66ABC");
// New string will be at most 2x as long
char *new_str = calloc(strlen(str) * 2 + 1, 1);
int new_str_index = 0;
for (int i = 0; 0 != str[i]; i++) {
// Check for 6
if ('6' == str[i]) {
// Check for 2nd 6
if ('6' == str[i+1]) {
// Add chars
new_str[new_str_index++] = '^';
new_str[new_str_index++] = '^';
// Consume remaining 6s - double check this for off-by-one
while ('6' == str[i+1]) i += 1;
}
else {
// Add chars
new_str[new_str_index++] = '*';
new_str[new_str_index++] = '*';
}
}
// No 6s, just append text
else {
new_str[new_str_index++] = str[i];
}
}
OP asked for a simple way of altering the '6' characters in the string. If you want to write to another string instead of printing directly, I leave it to you to define the other (large enough) string, and copy the chars to that string instead of to stdout. But do NOT try to alter the string passed, it is doomed to fail.
#include <stdio.h>
void sixer(char *str)
{
int i = 0, sixes;
while(str[i] != '\0') {
if(str[i] == '6') {
sixes = 0;
while(str[i] == '6') {
sixes++;
i++;
}
if(sixes == 1) {
printf("**");
}
else {
printf("^^");
}
}
else {
printf("%c", str[i]);
i++;
}
}
printf("\n");
}
int main(void)
{
sixer("Hello6World66ABC");
sixer("6");
sixer("66666");
return 0;
}
Program output
Hello**World^^ABC
**
^^
void test(char text[], char testCipher[], int *längd, int *nyckel)
{
int i = 0;
int j = 0;
while(text[i] != '\0')
{
i++;
}
*längd = i - 1;
while(text[j] != '\0')
{
if(text[j] >= 'a' && text[j] <= 'z')
{
testCipher[j] = text[j] + 3;
j++;
*nyckel = *nyckel + 1;
}
}
}
int main()
{
char plainText[100];
char cipherText[100];
int length, key;
printf("Enter a text you want to encrypt: ");
fgets(plainText, 99, stdin);
test(plainText, cipherText, &length, &key);
printf("%d\n%s\n%d", length, cipherText, key);
return 0;
}
Terminal output
Enter a text you want to encrypt: ->After this nothing happens i can just input unlimited letters<-
Since i added the if-statement this started happening before that it worked.
You pass address of length and key to function which are unintialized . And then in function you do this -
*nyckel = *nyckel + 1;
*nyckel the address holds no value and you are trying to read it(basically I don't see use of this variable (??)) . Initialize both the variables before passing them to function or in function .
Consider what happens when your text contains a character that is not a letter -- the if means that you don't do anything with that character, and don't go on to the next character (don't increment j), so you just loop over the same character again...