c Print out the letters, which were repeatedly in string [duplicate] - c

This question already has answers here:
Bad permissions for mapped region [duplicate]
(2 answers)
Closed 9 years ago.
My function should print out letters which are more than once in string. I have no idea why I get an empty output, or my program 'stops working'.
#include <string.h>
#include <stdio.h>
void funkcja3 (char []);
int main()
{
funkcja3("napnapnaaw");
return 0;
}
void funkcja3 (char napis[])
{
int i=0,j;
for(;i<strlen(napis);i++)
{
if((napis[i]>='a')&&(napis[i]<='z'))
{
int n=0;
for(j=i+1;j<strlen(napis);j++)
{
if(napis[i]==napis[j])
{
n++;
napis[j]=' ';
}
}
if(n>0)
{
printf("%c ", napis[i]);
}
}
}
}

You need to pass a modifiable string:
int main()
{
char str[] = "napnapnaaw";
funkcja3(str);
return 0;
}

This is not a direct answer to your question, but if you just want to print out all the non-capital letters that appear more than once in a given string, then you can just use a histogram (symbol-counting) instead:
void funkcja3(char napis[])
{
int histogram['z'-'a'+1] = {0};
for (int i=0; napis[i]!=0; i++)
{
if ('a' <= napis[i] && napis[i] <= 'z')
histogram[napis[i]-'a']++;
}
for (int i=0; i<'z'-'a'+1; i++)
{
if (histogram[i] > 1)
printf("%c ",'a'+i);
}
}
BTW, histogram = the number of occurrences of each symbol in the data.

When I run your program on my machine (Ubuntu, gcc 4.6), I get a segmentation fault and a core dump. Giving the program and the core dump to gdb and doing a backtrace gives
$ gdb a.out core
Core was generated by `/tmp/a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005a2 in funkcja3 (napis=0x40072c "napnapnaaw") at a.c:25
25 napis[j]=' ';
(gdb) bt
bt
#0 0x00000000004005a2 in funkcja3 (napis=0x40072c "napnapnaaw") at a.c:25
#1 0x0000000000400520 in main () at a.c:8
This hint brings me to removing line 25 and running the program again
$ a.out
n a p n a a
which shows all characters, which were repeated somewhere later in the string.

When you call funkcja3, you're calling it with a string literal. This string literal is at a memory location that isn't modifiable, so the call to napid[j] = ' ' should fail (and does so when I copy your example in to visual studio 2013). What you need to do is either A: use std::string (or another string implementation) or B: make a copy of the string in the function, examine it, and then delete the copy when done. Either way, you probably shouldn't be modifying the original string going in to the function. It's generally bad practice to modify objects passed in to a function unless the function absolutely has to do so.
There are some other ways of completing this task as well, such as an array of 26 shorts to hold the counts for each character. Make those counts and then print out any character that has more then 1.

Related

Strcmp Problem Segmantation Fault insert method not working

I used GDB, and realised that the problem was reaching these line of codes:
in main:
'''
else if(strcmp("insert",arg[1])==0){
insert("a.txt","Cem","Mec","Cem","-a");
}
'''
insert method:
'''
void insert(char *filename, char *insertedWord, char *searchedWord,char *oldsearchedWord, char *ab){
if(strcmp("-a",ab) == 0){
strcat(searchedWord," ");
strcat(searchedWord, insertedWord);
replace(filename,searchedWord,oldsearchedWord);
}
else if(strcmp("-b",ab) == 0){
strcat(insertedWord," ");
strcat(insertedWord, searchedWord);
replace(filename,insertedWord,oldsearchedWord);
}
}
'''
and the error is:
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:32
32 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory.
I checked my replace method. It works.
You are trying to strcat using a string literal as target. You are not allowed to do this because string literals are usually placed on read only data segments and attempting to modify them is undefined behaviour.
switch to
char insertedWord[256] = "cem";
char searchedWord[256] = "mec";
...
and then pass those (modfiable) arrays instead.

Segmentation fault - weird debugging with gdb

I'm working in C, Linux terminal. I need to find a pattern in a text and recolor it. GDB debugging can locate the function that is causing the problem via (gdb) backtrace, but it shows me a terrible message when I try to find the exact line:
Error
Program received signal SIGSEGV, Segmentation fault.
strstr_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strstr-sse2-unaligned.S:40
40 ../sysdeps/x86_64/multiarch/strstr-sse2-unaligned.S: No such file or dir
ectory.
(gbd)
The broken function is find_and_recolor:
char* my_replace(char *text, char* replacement)
{
int lgreplacement = strlen(replacement);
int lgtext = strlen(text);
char *aux = (char*)malloc((lgreplacement + lgtext + 10) * sizeof(char));
strcpy(aux, replacement);
strcat(aux, text);
return(aux);
}
char* find_and_recolor(char* text, char* pattern)
{
int lgpattern = strlen(pattern);
int lgreplace = lgpattern + 10;//there are exactly 10 characters that must be inserted along the pattern word
int dif = 0;
char *p;
char *replacement = (char*)malloc(lgreplace * sizeof(char));
strcpy(replacement, "\e[0;31m");
strcat(replacement, pattern);
strcat(replacement, "\e[m");//to recolor a word in red, that word must be surrounded by those characters
while(p = strstr(text + dif, pattern))
{
p = my_replace(p, replacement);
p += lgreplace;
dif = p - text;
}
free(replacement);
return strdup(text);
}
it shows me a terrible message when I try to find the exact line:
There is nothing terrible, weird or unusual about this message, you just need to learn proper debugging technique.
What's happening is that the segmentation fault doesn't happen in your code, it happens inside GLIBC code (inside strstr), because you called strstr with bad arguments.
To find which call to strstr that was, use GDB up command to step out of GLIBC code, and into your code. Once you are inside find_and_recolor, you would be able to see the exact line, and print values of text, dif and pattern which caused your crash (assuming you compiled your code for debugging, i.e. with the -g flag).
Updating diff to p-text in while loop where both pointer points to different array doesn't make sense. It is undefined behavior.
Also code has other issues.
Uninitialized variable.
Less optimized as number of call can be reduced.

C : stack smashing detected but everything is working before return statement

Ok so there are lots of stack smashing detected questions on stackoverflow, I looked at 6-7 of them but couldn't clear my problem.
I have a void function in C named encryptor, which takes a char array, and updates that array.
void encryptor(char* m,char* K){
char T[5] = "1011\0"; // added the last '\0'
int l = countOnes(K);
for (int i=0; i<l; i=i+1){
char TT[33];
TT[32] = '\0'; // Last character is '\0'
strcat(TT,T); strcat(TT,T); strcat(TT,T); strcat(TT,T); strcat(TT,T); strcat(TT,T); strcat(TT,T); strcat(TT,T); // 8 times
string_xor(m,TT,m);
addOne(T);
}
printf("%s\n", m); // <======*** This print is working
// The output of print is correct encrypted bitstring
// of length 32 : 11011101110111011101110111011101
return;
}
And here is the the corresponding int main code :
int main(){
char message[33] = "11001100110011001100110011001100";
message[32]='\0';
char key[33] = "00100010001000100010001000100011";
key[32]='\0';
// encryptor takes a 32 bitstring and uses key to encrypt it
// All other functions in encryptor are working and even m is being updated
encryptor(message,key);
}
As the flow of program is reaching to the print function just before the return statement and after that stack smashing is detected what could be a possible reason for this
I tried to use gdb debugger but it shows
Program received signal SIGABRT, Aborted.
0x00007ffff7a55860 in raise () from /usr/lib/libc.so.6
Could anyone help me finding out (or any way to find out) the cause of this error (I dont think its because of buffer overflow or something as it reached the print function)
Thanks
Found the big blunder, strcat does not copies the T string to TT but does something via reference.
And as this pointer is referenced to a something created in function's frame which destroys after end of function it throws an error.
As character array is basically a pointer, as soon as the function returns that pointers turns garbage values and error comes.

How to use the array from another function in main?

Edit: I made some changes at my code.
I want to write a line fitting program by using the data from two .txt file. The code is as following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int data_read(char programs_x[], char programs_y[]) {
int i=0, j=0, k;
int numProgs_x=0;
int numProgs_y=0;
char line_x[1024];
char line_y[1024];
FILE *file_x;
FILE *file_y;
file_x = fopen("data_x.txt", "r");
file_y = fopen("data_y.txt", "r");
while(fgets(line_x, sizeof line_x, file_x)!=NULL) {
//check to be sure reading correctly
//printf("%s", line_x);
//add each filename into array of programs
programs_x[i]=strdup(line_x);
i++;
//count number of programs in file
numProgs_x++;
}
while(fgets(line_y, sizeof line_y, file_y)!=NULL) {
//check to be sure reading correctly
//printf("%s", line_y);
//add each filename into array of programs
programs_y[j]=strdup(line_y);
j++;
//count number of programs in file
numProgs_y++;
}
fclose(file_x);
fclose(file_y);
return 0;
}
int main ( void ) {
int i, j, k, n=1024;
float s1=0,s2=0,s3=0,s4=0,a,d,b;
char programs_x[1024], programs_y[1024];
data_read(programs_x, programs_y);
for(i=0;i<n;i++) {
scanf("%f", &programs_x[k]);
}
for(i=0; i<n; i++){
scanf("%f", &programs_y[k]);
}
for(i=0;i<n;i++) {
s1=s1+programs_x[i];
s2=s2+programs_x[i] * programs_x[i];
s3=s3+programs_y[i];
s4=s4+programs_x[i] * programs_y[i];
}
d=n*s2-s1*s1;
a=(s2*s3-s1*s4)/d;
b=(n*s4-s1*s3)/d;
printf("\nThe values of a and b are : %f\t%f\n",a,b);
printf("\nThe Required Linear Relation is : \n");
if(b>0){
printf("\ny=%f+%fx\n",a,b);
}
else {
printf("y=%f%fx",a,b);
}
return 0;
}
When I try to compile this code, the compiler shows these error:
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test3.c:
Error E2349 test3.c 22: Nonportable pointer conversion in function data_read
Error E2349 test3.c 33: Nonportable pointer conversion in function data_read
*** 2 errors in Compile ***
How do I fix the errors? Where did I make mistakes in declaring and calling the data types? I'm pretty sure I declare programs_x and programs_y as char this time and not int.
The error is difficulty to pin down as we don't have line numbers but this line is definitely not right in your main:
data_read(char programs_x[], char programs_y[]);
To call a function you just list the variables and values you're passing to it like this:
data_read(programs_x, programs_y);
Which will no doubt cause more errors/warnings to be flagged as you declare programs_x and programs_y as arrays of int, but data_read is expecting arrays of char. So there's a conflict in what you think your function wants and what you're providing to it which you need to sort out.
The error could mean that the non-standard function strdup() is not supported. A C compiler does not need to support it, which is why it is a good idea to avoid that function. If the function is supported as a non-standard extension (it is part of POSIX), you might find it in the header <string.h> which you didn't include.
As for the cause of the rest of the errors, I have no idea, since those appear to originate from other files than the one you posted.

Accessing the 'strdup' of a static array from a different file

I use the get_sessionid() function below from a thread function and then try to free that pointer.
static char sessionid[SESSIONID_LEN] = { '\0' };
static void generate_sessionid() {
char set[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int len;
memset(sessionid, 0, sizeof(char) * SESSIONID_LEN);
for (len = 0; len < SESSIONID_LEN; len++) {
size_t index = (double) rand()/RAND_MAX*(sizeof(set) - 1);
sessionid[len] = set[index];
}
}
char *get_sessionid() {
if (strlen(sessionid) == 0) generate_sessionid();
return strdup(sessionid);
}
When I debug into the thread function from which I call the above get_sessionid, I noticed that the session id returned is not NULL, but the program crashes with SIGABRT immediately when I try to free that pointer. I don't double free the pointer either which can raise an abort signal. I am not sure if thread safety is an issue here.
Also the thread function is defined in a different file.
Edit:
I made the change as was suggested:
static char sessionid[SESSIONID_LEN+1] = { '\0' };
I still get SIGABRT after this edit.
Another thing to mention: I don't get this signal on other machines that I have but only on 1 particular machine that runs Debian Squeeze (Linux kernel: 2.6.32-5-amd64)
Edit 2:
From a different thread function, a segmentation fault is thrown when trying to access the pointer returned by get_sessionid(): SIGSEGV. This error is thrown on all the machines (unlike the previous error) and is reproducible.
And when I debug and try to print the value of the returned pointer in the calling thread function, I get:
<Address 0xfffffffffc005080 out of bounds>
You should define sessionid as
static char sessionid[SESSIONID_LEN+1] = { '\0' };
Then after
for (len = 0; len < SESSIONID_LEN; len++) {
sessionid still a valid C string (a sequence of characters and a '\0'), which is required by strdup().

Resources