So basically when I compile my code with a GCC compiler I get no error or warnings, but when I input the first piece of data it says:
Bus error: 10.
I'm not sure what I'm doing wrong. I think The problem is coming from void anagramGrouping (the last function). I also included the rest of the code to help follow the logic.
#include <stdio.h>
#include <string.h>
#define Row 2
#define col 20
int wordCount = 0;
int groupCount = 0;
char wordList[Row][col];
char group[Row][col];
// this is where prototypes go
void sortword(char word[col]);
void anagramGrouping(char word[col], char copy[col]);
void resetGroup();
int main() {
int i; // used in for loop to 'get' the strings
char word[col];
resetGroup();
for (i = 0; i < Row; i++) {
scanf("%s", word);
sortword(word);
wordCount++;
}
}
void resetGroup() {
int i;
for (i = 0; i < Row; i++)
strcpy(group[i], " ");
}
void sortword(char word[col]) {
int i = 0;
char temp;
char copy[col]; // used to store a copy of the original word
strcpy(copy, word);
while (word[i] != '\0') {
int j = i + 1;
while (word[j] != '\0') {
if (word[j] < word[i]) {
temp = word[i];
word[i] = word[j];
word[j] = temp;
}
j++;
}
i++;
}
anagramGrouping(word,copy);
}
void anagramGrouping(char word[col], char copy[col]) {
int n;
if (wordCount == 0) {
strcpy(group[0], copy);
}
for (n = 0; n <= groupCount; n++) {
if (strcmp(group[n], word) == 0) {
strcpy(group[n], copy);
} else {
groupCount++;
strcpy(group[groupCount], copy);
}
}
}
For starters, change all
sortword (char word[col])
to
sortword (char *word)
and all
anagramGrouping (char word[col], char copy[col])
to
anagramGrouping (char *word, char *copy)
When you pass char copy[col], you are passing a character array, which when passed as a function parameter is converted to a pointer. (you will hear the phrase "decays to a pointer", which isn't entirely correct, but is used often to mean the same thing). This isn't the problem causing the bus error, but will make your code much more readable.
Next, your bus error is generally due to the misuse of a pointer value which when the value is taken, falls outside the allowable memory range for your program, usually in the system area causing the bus error. Looking over your code, it is hard to tell which of the many issues may be the exact cause. However, a likely culprit is:
for(n=0; n <= groupCount; n++)
{
if ( strcmp(group[n],word) ==0 )
{
strcpy(group[n],copy);
}
else
{
groupCount++;
strcpy(group[groupCount],copy);
}
}
Where running through a debugger, you will quickly find that groupCount grows well beyond 1 causing strcpy(group[groupCount],copy) to write beyond the end of the char group[Row][col];. Where the allowable row values are limited to 0-1 as you #define Row 2.
To limit the copies to the allowable range, change the loop criteria to:
for (n = 0; n < Row; n++) {
A further cleanup of your code could look as follows:
#include<stdio.h>
#include<string.h>
#define Row 2
#define col 20
int wordCount = 0;
int groupCount = 0;
char wordList[Row][col];
char group[Row][col];
void sortword (char *word);
void anagramGrouping (char *word, char *copy);
void resetGroup();
int main (void) {
int i;
char word[col] = "";
resetGroup();
for (i = 0; i < Row; i++)
{
scanf ("%s", word);
sortword (word);
wordCount++;
}
return 0; /* main is a function of type 'int' and returns a value */
}
void resetGroup()
{
int i;
for (i = 0; i < Row; i++)
*group[i] = 0;
}
void sortword (char *word)
{
int i = 0;
char temp;
char copy[col] = "";
strcpy (copy, word);
while (word[i]) {
int j = i + 1;
while (word[j]) {
if(word[j] < word[i]) {
temp = word[i];
word[i] = word[j];
word[j] = temp;
}
j++;
}
i++;
}
anagramGrouping (word,copy);
}
void anagramGrouping (char *word, char *copy)
{
int n;
if (!wordCount)
strcpy (group[0],copy);
for (n = 0; n < Row; n++) {
if (strcmp (group[n], word) == 0)
strcpy(group[n],copy);
else {
groupCount++;
strcpy (group [groupCount],copy);
}
}
}
Let me know if you have any questions.
Related
I managed to sort it alphabetically but I need to sort it by the most frequent characters first after that. Since I'm new to C programming Im not sure if this alphabetical sort is needed. Also I thought about using a struct but not sure how to do the whole process with it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpfunc(const void *a, const void *b) {
return *(char*)a - *(char*)b;
}
void AlphabetOrder(char str[]) {
qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
printf("%s\n", str);
}
void Max_Occurring(char *str)
{
int i;
int max = 0;
int freq[256] = {0};
for(i = 0; str[i] != '\0'; i++)
{
freq[str[i]] = freq[str[i]] + 1;
}
for(i = 0; i < 256; i++)
{
if(freq[i] > freq[max])
{
max = i;
}
}
printf("Character '%c' appears %d times", max, freq[max], str);
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
AlphabetOrder(str1);
Max_Occurring(str1);
return 0;
}
I wrote you a frequency sorter using the idea that #WeatherVane mentioned:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cfreq {
unsigned char c;
int freq;
};
int freqcmp(const void *a, const void *b) {
struct cfreq *a2 = (struct cfreq *) a;
struct cfreq *b2 = (struct cfreq *) b;
if(a2->freq < b2->freq) return -1;
if(a2->freq == b2->freq) return 0;
return 1;
}
int freqcmpdesc(const void *a, const void *b) {
return -freqcmp(a, b);
}
void FrequencyOrder(const char str[]) {
struct cfreq cfreqs[256];
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
cfreqs[i].c = i;
cfreqs[i].freq = 0;
}
for(int i = 0; str[i]; i++) cfreqs[str[i]].freq++;
qsort(cfreqs, sizeof(cfreqs) / sizeof(*cfreqs), sizeof(*cfreqs), freqcmpdesc);
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
if(cfreqs[i].freq) printf("%c", cfreqs[i].c);
}
printf("\n");
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
FrequencyOrder(str1);
return 0;
}
and here is a sample session (note: output is not deterministic for letters with same frequency):
Enter a string: buzz
zbu
If you want duplicate letters in the output then replace the print with a loop along these lines:
while(cfreqs[i].freq--) printf("%c", cfreqs[i].c);
Im not sure if this alphabetical sort is needed.
It is not needed, yet if done, Max_Occurring() can take advantage of a sorted string.
Since the string is sorted before calling Max_Occurring(), compute the max occurring via a count of adjacent repetitions of each char.
// Untested illustrative code.
// str points to a sorted string.
void Max_Occurring(const char *str) {
char max_ch = '\0';
size_t max_occurence = 0;
char previous = '\0';
size_t occurrence = 0;
while (*str) {
if (*str == previous) {
occurrence++;
} else {
occurrence = 1;
}
if (occurrence > max_occurence) {
max_occurence = occurrence;
max_ch = *str;
}
previous = *str;
str++;
}
printf("Character '%c' appears %zu times", max_ch, max_occurence);
}
In the case of multiple characters with the same max occurrence, this code only reports one max.
Avoid buffer overflow
Do not use scanf("%s"... without a width limit.
Tip: enable all warnings to save time and see the problem of using &str1 when str1 should be used.
char str1[20];
...
// scanf("%s", &str1);
scanf("%19s", str1);
Avoid a negative index
If still wanting to for a frequency table, watch out for the case when char is signed and code use str[i] < 0 to index an array.
Instead:
const unsigned char *ustr = (const unsigned char *) str;
size_t freq[UCHAR_MAX + 1] = {0};
for(size_t i = 0; ustr[i] != '\0'; i++) {
freq[ustr[i]]++;
}
Here's another alternative that may be simpler.
void freqOrder( char *p ) {
#define ASCIIcnt 128 // 7bit ASCII
// to count occurences of each character
int occur[ ASCIIcnt ];
memset( occur, 0, sizeof occur );
int maxCnt = 0; // remember the highest count
// do the counting
for( ; *p; p++ )
if( ++occur[ *p ] > maxCnt )
maxCnt = occur[ *p ];
// output most frequent to least frequen
for( ; maxCnt; maxCnt-- )
for( int i = 0; i < ASCIIcnt; i++ )
if( occur[i] == maxCnt )
while( occur[i]-- )
putchar( i );
putchar( '\n' );
}
int main( void ) {
freqOrder( "The quick brown fox jumps over the lazy dog" );
return 0;
}
Output
' ooooeeehhrruuTabcdfgijklmnpqstvwxyz'
I have written some code on to find the number of times the characters repeated in the string.Considered 2 pointers and allocated memory dynamically, then input the string into one of the pointers.Then copying the characters without redundancies into the another pointer and finally comparing it, incrementing the count and printing to the screen.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void string_cpy(char *from, char *to);
int len(char *p);
int main()
{
char *name, *copy, *hold;
int i, j, lent, count = 0, length;
name = (char *)calloc(25, sizeof(char));
copy = (char *)calloc(25, sizeof(char));
printf("Give a string:");
scanf("%s", name);
puts("");
string_cpy(name, copy);
hold = name;
lent = len(copy); //l=4
length = len(name); //lenght = 5
printf("Characters and their corresponding frequencies\n");
for (i = 0; i < lent; ++i)
{
for (j = 0; j < length;)
{
if (*(copy) == *(name))
{
++count;
++name;
++j;
}
else
{
++j;
++name;
}
}
name = hold;
printf("%c-%d\n", *(copy), count);
count = 0;
++copy;
}
free(name);
free(copy);
return 0;
}
void string_cpy(char *from, char *to)
{
int i, j, k, l, ex;
char key;
l = len(from); //l=5
char *t = to;
for (i = 0, j = 0; i < l; ++i)
{
key = *(from + i);
ex = 0;
for (k = 0; k < i; ++k)
{
if (*(to + k) == key)
{
ex = 1;
}
}
if (!ex)
{ //if(ex==0)
strcpy((to + j), (from + i));
++j;
}
}
}
int len(char *p)
{
int leng = 0;
while (*p != '\0')
{
++leng;
++p;
}
return leng;
}
when I try to free() up both the pointers or the '''char *copy''' it throws me an error
->malloc: *** error for object 0x120e06884: pointer being freed was not allocated
->malloc: *** set a breakpoint in malloc_error_break to debug
This was done on my Mac OS
You change the value of the calloced pointer. It does not reference anymore the allocated memory block.
++copy;
Please, help with the code.
Requirement:
Write a function my_union that takes two strings and returns, without doubles, the characters that appear in either one of the strings.
Example:
Input: "zpadinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output: "zpadintoqefwjy"
My code:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char *my_union(char *a, char *b) {
char *str;
// Algorithm for excluding nonunique characters from string a(given in
// parameters).
str[0] = a[0];
int k = 1;
str[k] = '\0';
for (int i = 1; a[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == a[i]) {
is = false;
break;
}
}
if (is) {
str[k] = a[i];
k++;
str[k] = '\0';
}
} // In this case we are excluding excess character 'n' from "zpadinton", so
// str is equal to "zpadinto".
// Algorithm for adding unique characters from array b(given in parameters)
// into str.
for (int i = 0; b[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == b[i]) {
is = false;
break;
}
}
if (is) {
strncat(str, &b[i], 1);
}
}
return str;
}
The first algorithm is almost identical with second, but it doesn't work(. Mb I messed up with memory, give some advice, pls.
If you mean, get the unique characters from two strings and store them into a new string, try this code ;
First, you must allocate a memory for str. In your code, str is not pointing allocated memory location, so you will probably get segmentation fault.
int contains(const char * str,char c)
{
for (int i = 0; i < strlen(str); ++i)
if(str[i] == c)
return 1;
return 0;
}
char * my_union(char *a, char*b)
{
char * res = (char*)malloc(sizeof(char)*(strlen(a) + strlen(b)));
int pushed = 0;
for (int i = 0; i < strlen(a); ++i)
{
if(!contains(res,a[i])){
res[pushed] = a[i];
pushed++;
}
}
for (int i = 0; i < strlen(b); ++i)
{
if(!contains(res,b[i])){
res[pushed] = b[i];
pushed++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
char string1[9] = "abcdefgh";
char string2[9] = "abegzygj";
char * result = my_union(string1,string2);
printf("%s\n", result);
return 0;
}
Also, do not forget the free the return value of my_union after you done with it.
I keep getting the error message that my I have an undefined reference to the power function, but I'm not really sure where that is occurring or why my code is coming up with that error because I have used to power function before in this way. If anyone could help me figure out why it isn't working now I would really appreciate it.
#include "stdio.h"
#include "string.h" //Needed for strlen()
#include "math.h"
#define MAX_BITS 32
#define MAX_LENGTH 49
#define NUMBER_TWO 2
#define NUMBER_ONE 1
#define TERMINATOR '\0'
//Code to find the index of where the string ends
int last_index_of(char in_str[], char ch) {
for (int i = 0; i < MAX_LENGTH; i++) {
if(in_str[i] == ch) {
last_index_of == i;
}
}
return last_index_of;
}
//Code to find the start of the fractional aspect
void sub_string(char in_str[], char out_str[], int start, int end){
int i = 0;
while (i < 1) {
out_str[i] = in_str[start] + in_str[end-1];
i++;
}
}
int main()
{
//Declaration of variable
char input[MAX_LENGTH +1]; // +1 for '\0'
int number;
double exponent;
char output[MAX_BITS];
int fraction;
sub_string(input, output, 0, TERMINATOR);
//Input from the user
printf("Enter a floating point value in binary: ");
scanf("%s", input);
//Calculates the Decimal Part
for (int i = 0; i < last_index_of(input, TERMINATOR) ; i++) {
number = number + number + input[i];
}
printf("%d", number);
exponent = -1;
//Calculates the Fractional Part
for (int j = 0; j < last_index_of(input, TERMINATOR); j++) {
if (j == last_index_of) {
fraction = NUMBER_ONE/(pow(NUMBER_TWO, exponent));
printf("%d/n", fraction);
}
else {
fraction = NUMBER_ONE/(pow(NUMBER_TWO, exponent));
printf("%d + ", fraction);
exponent--;
}
}
return 0;
}
Some problems:
you need -lm option to linker to tell it where to find pow function
last_index_of is not correctly written, you use the function name as an internal variable, you can correct it this way:
//Code to find the index of where the string ends
int last_index_of(char in_str[], char ch) {
int ret = 0;
for (int i = 0; i < MAX_LENGTH; i++) {
if(in_str[i] == ch) {
ret = i;
}
}
return ret;
}
Note that you can replace your last_index_of() function by strlen()
as pointed in comment, sub_string() is not functionnal. A corrected version could be:
//Code to find the start of the fractional aspect
void sub_string(char in_str[], char out_str[], int start, int end){
int i = 0;
while (start != end) {
/* warning, bounds are still not tested...*/
out_str[i++] = in_str[start++];
}
out_str[i] = '\0'
}
Instead of calling last_index_of() in your exist for loop condition, you should take its value to re-use it:
for (int j = 0; j < last_index_of(input, TERMINATOR); j++) {
/* Error here: will never be TRUE */
if (j == last_index_of) {
/* ... */
}
else {
/* ... */
}
}
would become:
int last_index = last_index_of(input, TERMINATOR);
for (int j = 0; j < last_index; j++) {
if (j == last_index) {
/* ... */
}
else {
/* ... */
}
}
Another problem, you use number variable without initializing it, you should write int number = 0 instead of int number;
After that, there is also a problem with your logic.
You have some idea of what you want to do, but it is not clear in your code.
It seems that you want
the user to input some string in the form 10010.100111
to split this string into two parts 10010 and 100111
to convert the first part into integer part 10010 -> 18
to convert the second part into fractional part 100111 -> 0.609...
This decomposition may lead you to write this kind of code:
#include "stdio.h"
#include "string.h"
#define MAX_BITS 32
#define MAX_LENGTH 49
//Code to find the index of where the string ends
int last_index_of(char in_str[], char ch)
{
int ret = 0;
for (int i = 0; i < MAX_LENGTH; i++) {
if (in_str[i] == ch) {
ret = i;
}
}
return ret;
}
void sub_string(char in_str[], char out_str[], int start, int end)
{
int i = 0;
while (start != end) {
/* warning, bounds are still not tested... */
out_str[i++] = in_str[start++];
}
out_str[i] = '\0';
}
void split(char *input, char *first, char *second)
{
int idx = last_index_of(input, '.');
sub_string(input, first, 0, idx);
sub_string(input, second, idx + 1, strlen(input));
}
int main()
{
//Declaration of variable
char input[MAX_LENGTH + 1]; // +1 for '\0'
char first[MAX_BITS];
char second[MAX_BITS];
/* Input from the user */
printf("Enter a floating point value in binary: ");
scanf("%s", input);
/* split integer and fractionnal parts */
split(input, first, second);
/* decode integer part */
printf("integer part:\n");
for (int i = strlen(first) - 1, j = 1; i > -1; --i, j <<= 1) {
if (first[i] == '1') {
printf("%d ", j);
}
}
/* decode frac part */
printf("\nfractionnal part:\n");
for (int i = 0; i < strlen(second); ++i) {
if (second[i] == '1') {
printf("1/%d ", 2 << i);
}
}
return 0;
}
My homework requires me to write a program that takes a string from the terminal (argc and argv) and print every possible permutation. I have tried to use Heap's Algorithm, but it doesn't seem to be working out. Below is my function.
char **getPermutation(char * in)
{
//n is the size of the input string.
int n = strlen(in);
int count[n];
int counter= 0;
char copy[n];
char **permutations = malloc(sizeof(char*)*(factorial(n)));
permutations[0] = in;
strcpy(in, copy);
counter++;
for( int i = 1; i < n;)
{
if (count[i] < i){
if (i%2==0){
swap(&in[0],&in[i]);
}
else
{
swap(&in[count[i]],&in[i]);
}
permutations[counter] = in;
strcpy(in, copy);
counter++;
count[i]++;
i = 1;
}
else
{
count[i] = 0;
i++;
}
}
return permutations;
}
The function must return the pointer to the character pointer as specified by the instructions. That's also why there are so many variables (although, I'm not really sure what to do with the copy of the string. I'm fairly sure I need it). Testing shows that the program will loop, often too much and eventually hit a seg fault. It doesn't seem like the swapped strings make it into the returned array on top of that.
Below is a rework of your code with cleaned up memory allocation and it addresses some problems mentioned in the above comments. Additionally, you have a bug in your algorithm, this statement strcpy(in, copy); keeps you from getting all the permutations (causes repeats instead.) This code works but isn't finished, it can use more error checking and other finishing touches:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int factorial(unsigned int n)
{
/* ... */
}
void swap(char *a, char *b)
{
/* ... */
}
char **getPermutations(const char *input)
{
char *string = strdup(input);
size_t length = strlen(string);
char **permutations = calloc(factorial(length), sizeof(char *));
int *counts = calloc(length, sizeof(int)); // point to array of ints all initialized to 0
int counter = 0;
permutations[counter++] = strdup(string);
for (size_t i = 1; i < length;)
{
if (counts[i] < i)
{
if (i % 2 == 0)
{
swap(&string[0], &string[i]);
}
else
{
swap(&string[counts[i]], &string[i]);
}
permutations[counter++] = strdup(string);
counts[i]++;
i = 1;
}
else
{
counts[i++] = 0;
}
}
free(counts);
free(string);
return permutations;
}
int main(int argc, char *argv[])
{
char *string = argv[1];
char **permutations = getPermutations(string);
unsigned int total = factorial(strlen(string));
for (unsigned int i = 0; i < total; i++)
{
printf("%s\n", permutations[i]);
}
free(permutations);
return 0;
}
OUTPUT
> ./a.out abc
abc
bac
cab
acb
bca
cba
>