I have code like this:
char str[100];
int r = 0;
for(int k = 0; k < i;k++){
str[r++] = y[k];
sprintf(str[r], str, x[k]);
r++;
}
I want in array y I have only alphabetic characters(e.g C,D...) and in array x I have only numbers. I want to make string like "C50D80E20" etc."
But I dont know how to put interger into string(I know I´m using sprintf wrong and also that it shouldn´t be used in this case).
Thanks in advance.
Here you are.
#include <stdio.h>
int main(void)
{
enum { N = 100 };
char s[N];
char a[] = "CDE";
int b[] = { 50, 80, 20 };
int pos = 0;
for ( size_t i = 0; i + 1 < sizeof( a ); i++ )
{
pos += sprintf( s + pos, "%c%d", a[i], b[i] );
}
s[pos] = '\0';
puts( s );
return 0;
}
The program output is
C50D80E20
This statement
s[pos] = '\0';
is required only in the case when there are no values to append to the array s that is when none call of sprintf was executed.
If you want to get a string like this
C50 D80 E20
then just write for example
pos += sprintf( s + pos, "%c%d%c", a[i], b[i], ' ' );
And if you want to remove the last space character then instead of
s[pos] = '\0';
write
s[ pos == 0 ? pos : pos - 1 ] = '\0';
Instead of the function sprintf you could use the function snprintf. But it does not resolve the problem if you allocated not enough memory for the result string because in any case you will not get the expected result in such a case.
As for the function itoa then it is not a standard C function.
Use itoa().
Somthing like that:
itoa(y[k], str[r++], 10);
Here's a link about itoa().
UPDT:
Or as correctly commentator marked - you can use int + '0'
Is there any proper way how to put integer into string? [C]
Use snprintf().
Check results.
char str[N];
int len = snprintf(str[r], sizeof str, "%d", x[k]);
if (len < 0 || (unsigned)len >= sizeof str) Handle_Error();
Related
This program, tokenizes a user input string, removes extra spaces and saves each word into a 2D array and then print the tokens
EXAMPLE:
input: " Hello world string house and car"
output and EXPECTED output:
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
THE PROBLEM:
the problem is that I achieved this by using strlen() function when printing the tokens(code located at the very bottom), I am not supposed to use any other library than stdio.h and stdlib.h, since strlen() function is defined in string.h i tried to use sizeof(arr) / sizeof(arr[0]); but it does not work as I want, the result using sizeof is :
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
�oken[6]: ��
token[7]: �
token[8]: ����
token[9]: �
token[10]:
I WOULD LIKE TO HAVE THE EXPECTED OUTPUT WITHOUT USING STRLEN()
#include<stdio.h>
#include <stdlib.h>
#define TRUE 1
char tokenize(char *str, char array[10][20])
{
int n = 0, i, j = 0;
for(i = 0; TRUE; i++)//infinite loop until is the end of the string '\0'
{
if(str[i] != ' '){
//position 1, char 1
array[n][j++] = str[i];// if, it is not space, we save the character
}
else{
array[n][j++] = '\0';//end of the first word
n++;// position for next new word
j=0;// start writting char at position 0
}
if(str[i] == '\0')
break;
}
return 0;
}
//removes extra spaces
char* find_word_start(char* str){
/*also removes all extra spaces*/
char *result = (char*) malloc(sizeof(char) *1000);
int c = 0, d = 0;
// no space at beginning
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){ // till end of sentence
result[d++] = str[c++]; //take non-space characters
if(str[c]==' ') { // take one space between words
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d-1] = '\0';
//print or return char?
return result;
free(result);
}
int main()
{
char str[]=" Hello world string dudes and dudas ";
//words, and chars in each word
char arr[10][20];
//call the method to tokenize the string
tokenize(find_word_start(str),arr);
int row = sizeof(arr) / sizeof(arr[0]);
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
for(int i = 0;i <= strlen(arr);i++)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
printf("token[%d]: %s\n", i, arr[i]);
return 0;
}
Your code using strlen() may appear the work in this instance but it is not correct.
strlen(arr) makes no semantic sense because arr is not a string. It happens in this case to return 5 because arr has the same address as arr[0], then you kludged it to work for the 6 word output by using the test i <= strlen(arr) in the for loop. The two values strlen(arr) and the number of strings stored in arr are not related.
The expression sizeof(arr) / sizeof(arr[0]) determines the run-time constant number arrays within the array of arrays arr (i.e. 10), not the number of valid strings assigned. It is your code's responsibility to keep track of that either with a sentinel value such as an empty string, or by maintaining a count of strings assigned.
I suggest you change tokenize to return the number of strings (currently it is inexplicably defined to return a char, but in fact only ever rather uselessly returns zero):
int tokenize( char* str, char array[][20] )
{
...
return n ;
}
Then:
int rows = tokenize( find_word_start(str), arr ) ;
for( int i = 0; i < rows; i++ )
{
printf( "token[%d]: %s\n", i, arr[i] ) ;
}
This program is supposed to print an input string backwards. Every single time it happens, though, I get garbage characters such as \340 or of the like. Why is it doing that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mattsentence[51];
mattsentence[50] = '\0';
gets(mattsentence);
char mask[sizeof(mattsentence)];
int i, j;
j = sizeof(mattsentence);
for (i = 0; i < sizeof(mask); i++)
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
printf("\n");
}
Your approach is wrong because you reverse the entire character array while it can be filled only partially. You should use standard C function strlen declared in header <string.h> that to determine the size of the entered string. Also to use gets is unsafe because you can overwrite memory beyond the character array. It now is excluded from the C Standard
Here is shown how the program can be written.
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
char mask[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[--n] = '\0';
for ( size_t i = 0; n != 0; i++ )
{
mask[i] = mattsentence[--n];
printf( "%c", mask[i] );
}
printf( "\n" );
return 0;
}
If to enter
Hello, Christiana S. F. Chamon
then the program output will be
nomahC .F .S anaitsirhC ,olleH
Take into account that to output a string in the reverse order there is no need to define a second character array.
If you want only to output the source string in the reverse order then the program can look like
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[n-1] = '\0';
while ( n != 0 )
{
printf( "%c", mattsentence[--n] );
}
printf( "\n" );
return 0;
}
sizeof() operator gives the size of the datatype. So, sizeof(mattsentence) will give you a value of 51. Then, sizeof(mask) will give you 51 again.
When you use that sizeof(mask) as for loop condition, you're basically going past the actual input values, thus pritning out garbage values.
What you want here is to use strlen() to find out the actual valid length of the entered string.
So, basically you need to take care of
Point 1: replace sizeof with strlen().
Point 2: Use of gets() is dangerous. Please use fgets() instead of gets().
Point 3: int main() should be int main(void). Put an expilicit return statement at the end of main(). Good Practice.
The modified code should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char mattsentence[51] = {0}; //always initalize local variables, here it's covering null termination , too.
fgets(mattsentence, 51, stdin); //fgets()
char mask[strlen(mattsentence) + 1]; // one more to store terminating '\0'
int i = 0, j = 0, k = 0;
j = strlen(mattsentence);
k = j;
for (i = 0; i < k; i++) // make use of k, don't call `strlen()` repeatedly
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
return 0; //added return statement
}
See changed code:
int main()
{
char mattsentence[51];
mattsentence[0] = '\0'; // initialization
gets(mattsentence);
char mask[strlen(mattsentence) + 1]; // +1 for string terminator '\0'
int i, j;
j = strlen(mattsentence);
for (i = 0; i < strlen(mattsentence); i++) // strlen of original string
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
}
There are several errors:
strlen() should be used to get length of string
for loop should be controlled according to input string, not output string
it is better to use fgets() instead of gets(): that way you can control how many character will be read from the input
I can't write a workable code for a function that deletes N characters from the string S, starting from position P. How you guys would you write such a function?
void remove_substring(char *s, int p, int n) {
int i;
if(n == 0) {
printf("%s", s);
}
for (i = 0; i < p - 1; i++) {
printf("%c", s[i]);
}
for (i = strlen(s) - n; i < strlen(s); i++) {
printf("%c", s[i]);
}
}
Example:
s: "abcdefghi"
p: 4
n: 3
output:
abcghi
But for a case like n = 0 and p = 1 it's not working!
Thanks a lot!
A few people have shown you how to do this, but most of their solutions are highly condensed, use standard library functions or simply don't explain what's going on. Here's a version that includes not only some very basic error checking but some explanation of what's happening:
void remove_substr(char *s, size_t p, size_t n)
{
// p is 1-indexed for some reason... adjust it.
p--;
// ensure that we're not being asked to access
// memory past the current end of the string.
// Note that if p is already past the end of
// string then p + n will, necessarily, also be
// past the end of the string so this one check
// is sufficient.
if(p + n >= strlen(s))
return;
// Offset n to account for the data we will be
// skipping.
n += p;
// We copy one character at a time until we
// find the end-of-string character
while(s[n] != 0)
s[p++] = s[n++];
// And make sure our string is properly terminated.
s[p] = 0;
}
One caveat to watch out for: please don't call this function like this:
remove_substr("abcdefghi", 4, 3);
Or like this:
char *s = "abcdefghi";
remove_substr(s, 4, 3);
Doing so will result in undefined behavior, as string literals are read-only and modifying them is not allowed by the standard.
Strictly speaking, you didn't implement a removal of a substring: your code prints the original string with a range of characters removed.
Another thing to note is that according to your example, the index p is one-based, not zero-based like it is in C. Otherwise the output for "abcdefghi", 4, 3 would have been "abcdhi", not "abcghi".
With this in mind, let's make some changes. First, your math is a little off: the last loop should look like this:
for (i = p+n-1; i < strlen(s); i++) {
printf("%c", s[i]);
}
Demo on ideone.
If you would like to use C's zero-based indexing scheme, change your loops as follows:
for (i = 0; i < p; i++) {
printf("%c", s[i]);
}
for (i = p+n; i < strlen(s); i++) {
printf("%c", s[i]);
}
In addition, you should return from the if at the top, or add an else:
if(n == 0) {
printf("%s", s);
return;
}
or
if(n == 0) {
printf("%s", s);
} else {
// The rest of your code here
...
}
or remove the if altogether: it's only an optimization, your code is going to work fine without it, too.
Currently, you code would print the original string twice when n is 0.
If you would like to make your code remove the substring and return a result, you need to allocate the result, and replace printing with copying, like this:
char *remove_substring(char *s, int p, int n) {
// You need to do some checking before calling malloc
if (n == 0) return s;
size_t len = strlen(s);
if (n < 0 || p < 0 || p+n > len) return NULL;
size_t rlen = len-n+1;
char *res = malloc(rlen);
if (res == NULL) return NULL;
char *pt = res;
// Now let's use the two familiar loops,
// except printf("%c"...) will be replaced with *p++ = ...
for (int i = 0; i < p; i++) {
*pt++ = s[i];
}
for (int i = p+n; i < strlen(s); i++) {
*pt++ = s[i];
}
*pt='\0';
return res;
}
Note that this new version of your code returns dynamically allocated memory, which needs to be freed after use.
Here is a demo of this modified version on ideone.
Try copying the first part of the string, then the second
char result[10];
const char input[] = "abcdefg";
int n = 3;
int p = 4;
strncpy(result, input, p);
strncpy(result+p, input+p+n, length(input)-p-n);
printf("%s", result);
If you are looking to do this without the use of functions like strcpy or strncpy (which I see you said in a comment) then use a similar approach to how strcpy (or at least one possible variant) works under the hood:
void strnewcpy(char *dest, char *origin, int n, int p) {
while(p-- && *dest++ = *origin++)
;
origin += n;
while(*dest++ = *origin++)
;
}
metacode:
allocate a buffer for the destination
decalre a pointer s to your source string
advance the pointer "p-1" positions in your source string and copy them on the fly to destination
advance "n" positions
copy rest to destination
What did you try? Doesn't strcpy(s+p, s+p+n) work?
Edit: Fixed to not rely on undefined behaviour in strcpy:
void remove_substring(char *s, int p, int n)
{
p--; // 1 indexed - why?
memmove(s+p, s+p+n, strlen(s) - n);
}
If your heart's really set on it, you can also replace the memmove call with a loop:
char *dst = s + p;
char *src = s + p + n;
for (int i = 0; i < strlen(s) - n; i++)
*dst++ = *src++;
And if you do that, you can strip out the strlen call, too:
while ((*dst++ = *src++) != '\0);
But I'm not sure I recommend compressing it that much.
Suppose I have an array and I want to remove elements from certain ranges of indices.
If I know ahead of time the size of the array, the size of every element in the array, and what ranges of indices I want to remove is there any way I can avoid copying over a new array?
If you don't want to use a new array for copying , you can think of doing this in the same array itself , here is what I have :
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "hello world";
int i , strt , end , j;
setbuf ( stdout , NULL );
printf ("enter the start and end points of the range of the array to remove:\n");
scanf ("%d%d", &strt , &end);
int len = strlen (str);
for ( i = end; i >= strt ;i--)
{
str[i-1] = str[i];
for ( j = i+1; j <= len ; j++)
{
str[j-1] = str[j];
}
len--;
}
printf ("%s" , str);
return 0;
}
While this code is for character arrays, you can also use the algorithm for integer arrays with slight modifications (do it as exercise ).
NOTE:- This method is not very efficient though , as you can see the exponential increase in the complexity , so my advice would be just to use the copying over new array method .
Hello you could do something like that.
int main(int ac, char **av)
{
char *str;
int i;
i = 0;
str = strdup("Hello World");
while(str[i])
{
if(i == 6) // 6 = W the range of the array you want to remove
str[i] = '\0';
i++;
}
printf("%s\n", str);
}
The output will be "Hello" instead of "Hello World".
I am new to cpp and have a question regarding arrays. The code I have below should create a reversed version of str and have it be stored in newStr. However, newStr always comes up empty. Can someone explain to me why this is happening even though I am assigning a value from str into it?
void reverse (char* str) {
char* newStr = (char*)malloc(sizeof(str));
for (int i=0;i<sizeof(str)/sizeof(char);i++) {
int index = sizeof(str)/sizeof(char)-1-i;
newStr [i] = str [index];
}
}
PS: I know that it is much more efficient to reverse an array by moving the pointer or by using the std::reverse function but I am interested in why the above code does not work.
As above commenters pointed out sizeof(str) does not tell you the length of the string. You should use size_t len = strlen(str);
void reverse (char* str) {
size_t len = strlen(str);
char* newStr = (char*)malloc(len + 1);
for (int i=0; i<len;i++) {
int index = len-1-i;
newStr[i] = str[index];
}
newStr[len] = '\0'; // Add terminator to the new string.
}
Don't forget to free any memory you malloc. I assume your function is going to return your new string?
Edit: +1 on the length to make room for the terminator.
The sizeof operator (it is not a function!) is evaluated at compile time. You are passing it a pointer to a region of memory that you claim holds a string. However, the length of this string isn't fixed at compile time. sizeof(str)/sizeof(char) will always yield the size of a pointer on your architecture, probably 8 or 4.
What you want is to use strlen to determine the length of your string.
Alternatively, a more idiomatic way of doing this would be to use std::string (if you insist of reversing the string yourself)
std::string reverse(std::string str) {
for (std::string::size_type i = 0, j = str.size(); i+1 < j--; ++i) {
char const swap = str[i];
str[i] = str[j];
str[j] = swap;
}
return str;
}
Note that due to implicit conversion (see overload (5)), you can also call this function with your plain C-style char pointer.
There are two issues here:
The sizeof operator won't give you the length of the string. Rather, it gives you the size of a char* on the machine you are using. You can use strlen() instead to get the
A c-string is terminated by a NULL character (which is why strlen() can return the correct length of the string). You need to make sure you are not accidentally copying the NULL character from your source string to the beginning of your destination string. Also, you need to add a NULL character at the end of your destination string or you will get some unexpected output.
#include <bits/stdc++.h>
using namespace std;
vector<string> split_string(string);
// Complete the reverseArray function below.
vector<int> reverseArray(vector<int> a) {
return {a.rbegin(), a.rend()};
}
int main()
{
ofstream fout(getenv("OUTPUT_PATH"));
int arr_count;
cin >> arr_count;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
string arr_temp_temp;
getline(cin, arr_temp_temp);
vector<string> arr_temp = split_string(arr_temp_temp);
vector<int> arr(arr_count);
for (int i = 0; i < arr_count; i++) {
int arr_item = stoi(arr_temp[i]);
arr[i] = arr_item;
}
vector<int> res = reverseArray(arr);
for (int i = 0; i < res.size(); i++) {
fout << res[i];
if (i != res.size() - 1) {
fout << " ";
}
}
fout << "\n";
fout.close();
return 0;
}
vector<string> split_string(string input_string) {
string::iterator new_end = unique(input_string.begin(), input_string.end(), [] (const char &x, const char &y) {
return x == y and x == ' ';
});
input_string.erase(new_end, input_string.end());
while (input_string[input_string.length() - 1] == ' ') {
input_string.pop_back();
}
vector<string> splits;
char delimiter = ' ';
size_t i = 0;
size_t pos = input_string.find(delimiter);
while (pos != string::npos) {
splits.push_back(input_string.substr(i, pos - i));
i = pos + 1;
pos = input_string.find(delimiter, i);
}
splits.push_back(input_string.substr(i, min(pos, input_string.length()) - i + 1));
return splits;
}