strcat() has a problem in xcode using gcc - c

if I compile with XCode at the height of strcat() the following error is returned:
Thread 1: EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode = 0x0)
while, if I compile from terminal (gcc -Wall program.c -o Out):
Illegal instruction: 4
lung2 is the length of s2.
MAX equals 30 and it is the array's maximum length.
Here is the code:
char s1[MAX] = { '\0' };
char s2[MAX] = { '\0' };
int flag = 0;
char *ptr;
unsigned long int lung1, lung2 = 0;
int verifica = 0;
j = 0;
...
while (j < lung1) {
ptr = strstr(s1, s2);
if (ptr) {
strncpy(ptr, "*", lung2);
strcat(s1, ptr + lung2);
flag = 1;
} else {
j++;
}
}

The code replaces each occurrence of s2 in s1 with an asterisk *.
On some platforms the behavior of strcat is undefined if the source and destination overlap, which is the case here since ptr points into s1.

Related

strlen() crashes when I call it

I am trying to write a simple piece of code that merges two strings together in even and odd indexes.
This is the code
void two_strings(char a[], char b[]) {
int counta = 0, countb = 0;
int lena = strlen(a);
int lenb = strlen(b);
int lenab = lena + lenb;
char ans[lenab];
for(int i = 0; i<strlen(ans); i++) {
if(i%2 == 0) {
ans[i] = a[counta];
counta++;
}
else {
ans[i] = b[countb];
countb++;
}
}
printf("%s\n", ans);
}
This is the main:
int main() {
char a[] = "hello";
char b[] = "bye";
two_strings(a, b);
return 0;
}
I have compiled it with -Wall and didn't get any warnings or errors, and I have tried it also with long instead of int just to check if that was the issue. when I run the code it doesn't get past the first strlen(a)
Strings in C are defined as a sequence of non-null bytes followed by a terminating null byte ('\0').
The following are equivalent strings
char one[] = "hello";
char two[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
Both of these would have a string length of 5, and occupy 6 bytes of memory.
String handling functions in the Standard Library expect this null-terminating byte, and you will invoke Undefined Behavior by passing a non-null-terminated array to them. strlen and printf (with %s) are examples of these kinds of functions.
In your two_strings function you are not allocating enough memory to store the null-terminating byte. You also make no attempt to place this null-terminating byte in the array.
Allocate an additional byte for the null-terminating byte, and do not attempt to take the string length of an uninitialized array.
void two_strings(char a[], char b[]) {
/* ... */
size_t length = strlen(a) + strlen(b);
char string[length + 1];
for (size_t i = 0; i < length; i++) {
/* ... */
}
string[length] = '\0';
/* ... */
}
Also note that size_t is the correct type to use when dealing with memory indexing, and is the type returned by strlen.
As for your algorithm, in the event where your input strings differ in length you will attempt to continue indexing one of the strings after you have already reached its end.
You will either want to: only take the smaller string's length of characters from the larger string, stopping when the smaller string has been exhausted; or, append the remaining characters of the larger string to the result after the smaller string has been exhausted.
A quick example of the second approach:
#include <stdio.h>
#include <string.h>
void zip_strings(const char *a, const char *b) {
size_t combined_length = strlen(a) + strlen(b);
char joined_string[combined_length + 1];
for (size_t i = 0; i < combined_length; i++) {
const char **src = i & 1 ? &b : &a;
if (!**src)
src = &a;
if (!**src)
src = &b;
joined_string[i] = *((*src)++);
}
joined_string[combined_length] = '\0';
puts(joined_string);
}
int main(int argc, char **argv) {
if (argc > 2)
zip_strings(argv[1], argv[2]);
}
./a.out hello computer
hceolmlpouter

Iterate through every char in string stored in an array

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;
}

C program behaves differently in gcc and llvm compiler

I wrote a program that consists of main and a function expand. The problem is that the code returns the intended result when compiled and run with Xcode (latest version) however when compiled and run with gcc compiler through terminal the code is stuck immediately after running (no warnings or errors!). This is the command I use to compile the code in the terminal:
gcc expand.c -o expand -Wall -pedantic -ansi
Below is my code. I have no idea what my problem is:
#include <stdio.h>
#define MAX_LEN 100
#define ATOI_GAP 48
void expand(char s1[], char s2[]);
int main()
{
int i;
char s2[MAX_LEN]; /* declare the target array */
char s1[4]; /* declare the source array */
s1[0] = 'a';
s1[1] = '-';
s1[2] = 'z';
s1[3] = '\0';
for(i = 0; i < MAX_LEN; ++i) { /* print s2 array */
printf("%d ", s2[i]);
}
expand(s1, s2);
for(i = 0; s2[i] != '\0'; ++i) { /* print s2 array */
printf("%c ", s2[i]);
}
return 0;
}
/* the function gets string s1 of format "letterX-letterY"
and fills the "-" with the consequent letters from letterX to
letterY. For example, if s1 = "a-d", then s2 will be "abcd"*/
void expand(char s1[], char s2[]) {
int start = s2[0] = s1[0]; /* the first letter of the array s2 is the same as that of the array s1 */
int stop = s1[2]; /* determine at which letter we need to stop */
int j;
printf("inside expand");
for(j = 1; j < stop - '0' - ATOI_GAP; ++j) {
s2[j] = ++start; /* fill in the gap */
}
s2[j] = '\0';
printf("finished expand");
}
Found the issue, I was incorrectly running the output C file. I previously exported the path with all my C output files, so to call the file in question I was just typing "filename" in the terminal. However, the exported path wasn't sourced properly so I wasn't getting any result. When I run the file as "./filename" everything is working.

C - What's wrong with my code (malloc, char*)

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.

Segmentation fault on char string reference

I have a small C++ function which reverses a string in place:
void reverse1(string& s, int start, int end) {
if (s.empty()) return;
char tmp;
while (start < end) {
tmp = s[end];
s[end] = s[start];
s[start] = tmp;
++start;
--end;
}
}
This function works fine. However, when I rewrite it in c as below, I came across a segment fault on statement 11.
5 void reverse2(char *s, int start, int end) {
6 if (!s) return;
7 char tmp;
8
9 while (start < end) {
10 tmp = s[end];
11 *(s + end) = *(s + start);
12 *(s + start) = tmp;
13 ++start;
14 --end;
15 }
16 }
Driver program that calls the function:
int main() {
/* Flavor1 works */
string a = "hello world2012!";
reverse1(a, 0, a.length() - 1);
/* Flavor2 does not - segmentation fault */
char *b = "hello world2012!";
reverse2(b, 0, strlen(b) - 1);
}
I use gcc v 4.6.1 to compile my program. When stepping through the code with gdb, the program crashes at runtime with segmentation fault.
The char string s is not a const. Can someone please suggest what's going on here? How do I fix this issue. Thanks.
Update:
The reverse2 function is called on a string literal. The problem is I was trying to modify the string literal. As Jim and H2CO3 pointed out, this is an undefined behavior.
Now what's the exact difference between a string object (a) initialized with a string literal and a string literal (b)?
It depends on how you invoke your routine. If end is the length of the array, as is common in C, then s[end] is not a valid reference ... it's one character beyond s.
Also, !s is not equivalent to C++ s.empty ... it tests whether the pointer is NULL, rather than whether the string is empty -- for that, use !*s, !s[0], s[0] == '\0', strlen(s) == 0, etc.
The char string s is not a const.
It could fail anyway if it's a string literal constant; writing to such a string is Undefined Behavior.
you can rewrite the code as below
void reverse(char *s, int start, int end) {
if (!s) return;
char tmp;
if( end >= strlen(s) )
end = strlen(s)-1;
while (start < end) {
tmp = s[end];
*(s + end) = *(s + start);
*(s + start) = tmp;
++start;
--end;
}
}

Resources