Convert arabic number (long long int) to words in C - c

I would like to convert a number, let's say, 1024 or 2345787654 into english words, such that for 1024 it should print one thousand twenty four etc.
However, my code gives me segmentation fault. I tried to run it with gdb but is suggests that the problem is inside my_strcat function. However, I do not see any problem with this function. Please, help.
#include <stdlib.h>
#include <string.h>
const char *digits[] = { NULL, "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine " };
const char *tens[] = { NULL, "ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " };
const char *teens[] = { "ten ", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen " };
const char *scales[] = { "", "thousand ", "million ", "billion " };
char *my_strcat ( char **dest, const char * src)
{
char *tab = malloc ( sizeof ( char) * (strlen ( *dest) + strlen ( src) + 1));
if ( NULL == tab)
return NULL;
strcpy ( tab, *dest);
strcat ( tab, src);
free ( *dest);
*dest = malloc ( sizeof ( char) * ( strlen ( tab) + 1));
strcpy ( *dest, tab);
return tab;
}
char * LongToEnglish(unsigned long x)
{
switch(x)
{
case 0:
return "Zero";
case 1:
return "One";
case 2:
return "Two";
case 3:
return "Three";
case 4:
return "Four";
case 5:
return "Five";
case 6:
return "Six";
case 7:
return "Seven";
case 8:
return "Eight";
case 9:
return "Nine";
case 10:
return "Ten";
case 11:
return "Eleven";
case 12:
return "Twelve";
case 13:
return "Thirteen";
case 14:
return "Fourteen";
case 15:
return "Fifteen";
case 16:
return "Sixteen";
case 17:
return "Seventeen";
case 18:
return "Eighteen";
case 19:
return "Nineteen";
case 20:
return "Twenty";
case 30:
return "Thirty";
case 40:
return "Forty";
case 50:
return "Fifty";
case 60:
return "Sixty";
case 70:
return "Seventy";
case 80:
return "Eighty";
case 90:
return "Ninety";
case 100:
return "One Hundred";
case 1000:
return "One Thousand";
case 1000000:
return "One Million";
case 1000000000:
return "One Billion";
}
// less than 100
for (long i = 1; i <= 9; i ++)
{
long j = i * 10;
if ((x >= j) && (x < j + 10))
{
long r = x - j;
if(r > 0)
return my_strcat(my_strcat(*LongToEnglish(j), " "), LongToEnglish(r));
else
return my_strcat(*LongToEnglish(j), "");
}
}
// less than 1000
for (long i = 1; i <= 9; i ++)
{
long j = i * 100;
if ((x >= j) && (x < j + 100))
{
long r = x - j;
if(r > 0)
return my_strcat(my_strcat(LongToEnglish(i), " Hundred "), LongToEnglish(r));
else
return my_strcat(LongToEnglish(i), " Hundred");
}
}
// less than 10000
for (long i = 1; i <= 9; i ++)
{
long j = i * 1000;
if ((x >= j) && (x < j + 1000))
{
long r = x - j;
if(r > 0)
return my_strcat(my_strcat(LongToEnglish(i), " Thousand "), LongToEnglish(r));
else
return my_strcat(LongToEnglish(i), " Thousand");
}
}
// Million
for (long i = 1; i <= 9; i ++)
{
long j = i * 1000000;
if ((x >= j) && (x < j + 1000000))
{
long r = x - j;
if(r > 0)
return my_strcat(my_strcat(LongToEnglish(i), " Million "), LongToEnglish(r));
else
return my_strcat(LongToEnglish(i), " Million");
}
}
// Billion
for (long i = 1; i <= 4; i ++)
{
long j = i * 1000000000;
if ((x >= j) && (x < j + 1000000000))
{
long r = x - j;
if(r > 0)
return my_strcat(my_strcat(LongToEnglish(i), " Billion "), LongToEnglish(r));
else
return my_strcat(LongToEnglish(i), " Billion");
}
}
// Divide the number into 3-digit groups from left to right
char* output = "";
long cnt = 0;
while (x > 0)
{
long y = x % 1000;
x /= 1000;
if (y > 0) // skip middle-chunk zero
{
char * t = "";
if (cnt == 1) t = " Thousand ";
if (cnt == 2) t = " Million ";
if (cnt == 3) t = " Billion ";
output = my_strcat(my_strcat(LongToEnglish(y), t), output);
}
cnt ++;
}
return (output);
}
char* numberToWords(int num)
{
return LongToEnglish(num);
}
int main(int argc, char **argv)
{
char *dst = NULL;
dst = malloc ( sizeof ( char) * 10000000);
unsigned long long n = 122334;
dst = numberToWords(n);
printf("%s", dst);
free(dst);
return 0;
}

There are other problems in your code, I tell just one. When input is n=3 in main, numberToWords returns "Three" and you try to call free("Three"), etc.
You return a static string sometimes and try to free it for this particular case.

The task is for groups of thousands allways the same. So you can do it much less complicated.
The string handling might be optimized...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *digits[] = { NULL, "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine ", "ten ", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen " };
const char *tens[] = { NULL, "ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " };
const char *scales[] = { "", "thousand ", "million ", "billion " };
char *long2words(long x, int grp) {
char *buf = malloc(4096), *bp;
int e,t,h;
*buf='\0';
e = x%10;
t = (x/10)%10;
h = (x/100)%10;
x /=1000;
if(x!=0) {
strcat(buf, bp=long2words(x,grp+1));
free(bp);
}
if(h!=0) {
strcat(buf, digits[h]);
strcat(buf,"hundred ");
}
if(t<2) strcat(buf, digits[t*10+e]);
else {
strcat(buf, tens[t]);
strcat(buf, digits[e]);
}
strcat(buf, scales[grp]);
return buf;
}
int main()
{
printf(long2words(102410241024,0));
return 0;
}

Related

(Linux Kernel) Adding new functions in available_filter_functions

Hardware - Raspberry pi 4 Model B 8GB
OS - Raspberry pi OS Buster(10)(2020-05-27-raspios-buster-full-armhf.img)(linux kerenl 4.19.y)
I added rpi_get_interrupt_info() and modified show_interrupts() in proc.c
Full code for rpi_get_interrupt_info() and show_interrupts()
void rpi_get_interrupt_info(struct irqaction *action_p)
{
unsigned int irq_num = action_p->irq;
void *irq_handler = NULL;
if (action_p->handler) {
irq_handler = (void*)action_p->handler;
}
if (irq_handler) {
trace_printk("[%s] %d: %s, irq_handler: %pS \n",
current->comm, irq_num, action_p->name, irq_handler);
}
}
int show_interrupts(struct seq_file *p, void *v)
{
static int prec;
unsigned long flags, any_count = 0;
int i = *(loff_t *) v, j;
struct irqaction *action;
struct irq_desc *desc;
if (i > ACTUAL_NR_IRQS)
return 0;
if (i == ACTUAL_NR_IRQS)
return arch_show_interrupts(p, prec);
/* print header and calculate the width of the first column */
if (i == 0) {
for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
j *= 10;
seq_printf(p, "%*s", prec + 8, "");
for_each_online_cpu(j)
seq_printf(p, "CPU%-8d", j);
seq_putc(p, '\n');
}
rcu_read_lock();
desc = irq_to_desc(i);
if (!desc)
goto outsparse;
if (desc->kstat_irqs)
for_each_online_cpu(j)
any_count |= *per_cpu_ptr(desc->kstat_irqs, j);
if ((!desc->action || irq_desc_is_chained(desc)) && !any_count)
goto outsparse;
seq_printf(p, "%*d: ", prec, i);
for_each_online_cpu(j)
seq_printf(p, "%10u ", desc->kstat_irqs ?
*per_cpu_ptr(desc->kstat_irqs, j) : 0);
raw_spin_lock_irqsave(&desc->lock, flags);
if (desc->irq_data.chip) {
if (desc->irq_data.chip->irq_print_chip)
desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
else if (desc->irq_data.chip->name)
seq_printf(p, " %8s", desc->irq_data.chip->name);
else
seq_printf(p, " %8s", "-");
} else {
seq_printf(p, " %8s", "None");
}
if (desc->irq_data.domain)
seq_printf(p, " %*d", prec, (int) desc->irq_data.hwirq);
else
seq_printf(p, " %*s", prec, "");
#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
#endif
if (desc->name)
seq_printf(p, "-%-8s", desc->name);
action = desc->action;
if (action)
rpi_get_interrupt_info(action);
if (action) {
seq_printf(p, " %s", action->name);
while ((action = action->next) != NULL)
seq_printf(p, ", %s", action->name);
}
seq_putc(p, '\n');
raw_spin_unlock_irqrestore(&desc->lock, flags);
outsparse:
rcu_read_unlock();
return 0;
}
#endif
Code that I changed
void rpi_get_interrupt_info(struct irqaction *action_p)
{
unsigned int irq_num = action_p->irq;
void *irq_handler = NULL;
if (action_p->handler) {
irq_handler = (void*)action_p->handler;
}
if (irq_handler) {
trace_printk("[%s] %d: %s, irq_handler: %pS \n",
current->comm, irq_num, action_p->name, irq_handler);
}
}
....
if (action)
rpi_get_interrupt_info(action);
When I try
echo rpi_get_interrupt_info > /sys/kernel/debug/tracing/set_ftrace_filter,
an error occurs:
echo: write error: Invalid argument
So I looked /sys/kernel/debug/tracing/available_filter_functions, and there's no rpi_get_interrupt_info
I tried noinline void rpi_get_interrupt_info(struct irqaction *action_p), but it doesn't work.
Sorry, I was making some mistakes in configureing bcm2711_defconfig file. Thanks for everyone for trying to help me:)

I have got a problem with reading binary file into array of structures in c

Here is part of my code:
Here I want to transfer already saved .bin file into a new database structure student s, but it is not transferring more than one member of a structure.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[20];
int date;
int month;
int year;
int id;
int pnum;
}student;
int count = 0;
void swap(student* s1, student* s2) {
student* temp;
temp = s1;
s1 = s2;
s2 = temp;
}
void sort(student* s) {
for (int i = 0; i < count - 1; i++) {
for (int j = i + 1; j < count; j++) {
if (strcmp((s + i)->name, (s + j)->name) > 0) {
student temp = *(s + i);
*(s + i) = *(s + j);
*(s + j) = temp;
}
}
}
}
void addInf(student* s) {
printf("\t==================================Adding information=====================================\n\n");
printf("\t\tPlease input following information: \n");
printf("\tName: ");
scanf("%s", (s + count)->name);
printf("\tDate of birth (yyyymmdd): ");
scanf("%4d%2d%2d", &(s + count)->year, &(s + count)->month, &(s + count)->date);
printf("\tStudent ID: ");
scanf("%d", &(s + count)->id);
printf("\tPhone number: ");
scanf("%d", &(s + count)->pnum);
count++;
printf("\tEntry succeded.\n");
printf("\t=========================================================================================\n\n");
}
void print(student* s) {
printf("\t\tName: %s\n", s->name);
printf("\t\tBidthday: %d/%02d/%02d\n", s->year, s->month, s->date);
printf("\t\tID: %d\n", s->id);
printf("\t\tPhone number: %d\n", s->pnum);
}
void delInf(student* s, int n) {
int com;
printf("\t=================================Deleting information====================================\n\n");
printf("\t=========================================================================================\n\n");
char name[20];
printf("\t\tPlease input name of the student that you want to delete: ");
scanf("%s", &name);
for (int i = 0; i < count; i++) {
if ((strcmp(name, (s + i)->name)) == 0) {
printf("\t\tInformation that you want to delete\n");
print((s + i));
for (int j = i; j < count; j++) {
*(s + i) = *(s + i + 1);
count--;
printf("\t\tInformation was succesfully deleted.\n\n");
}
}
}
}
void searchByID(student* s) {
int key;
printf("\t======================================Searching by ID====================================\n\n");
printf("\t\tEnter ID: ");
scanf("%d", &key);
printf("\t=========================================================================================\n\n");
int i;
for (i = 0; i < count; i++) {
if (key == (s + i)->id) {
break;
}
}
print((s + i));
}
void searchByName(student* s) {
char key[20];
int i;
int size, check = 0;
printf("\t======================================Searching by Name==================================\n\n");
printf("\t\tEnter Name: ");
scanf("%s", &key);
printf("\t=========================================================================================\n\n");
for (i = 0; i < count; i++) {
if (strcmp(key, (s + i)->name) == 0) {
print((s + i));
}
}
}
void searchByBirthDate(student* s) {
int key, command;
int i;
printf("\t================================Searching by Birthdate================================\n\n");
printf("\t\t1.By Date\t\t 2.By Month\t\t 3.By Year\t\t 4.By All\n");
printf("\t\tCommand: ");
scanf("%d", &command);
printf("\t=========================================================================================\n\n");
if (command == 1) {
printf("Enter date: ");
scanf("%2d", &key);
printf("\t\tStudent with same date\n");
for (i = 0; i < count; i++) {
if (key == (s + i)->date) {
printf("\t\t---------%d----------\n\n", i + 1);
print((s + i));
}
}
}
if (command == 2) {
printf("\t\tEnter month: ");
scanf("%2d", &key);
printf("\t\tStudent with same month\n");
for (i = 0; i < count; i++) {
if (key == (s + i)->month) {
printf("\t\t---------%d----------\n\n", i + 1);
print((s + i));
}
}
}
if (command == 3) {
printf("\t\tEnter year: ");
scanf("%4d", &key);
printf("\t\tStudent with same year\n");
for (i = 0; i < count; i++) {
if (key == (s + i)->year) {
printf("\t\t---------%d----------\n\n", i + 1);
print(s + i);
}
}
}
if (command == 4) {
int yy, mm, dd;
printf("\t\tEnter birthdate: ");
scanf("%4d%2d%2d", &yy, &mm, &dd);
for (i = 0; i < count; i++) {
if (yy == (s + i)->year && mm == (s + i)->month && dd == (s + i)->date) {
break;
}
}
print(s + i);
}
}
void printTable(student* s) {
printf("\t============================================Table========================================\n\n");
printf("\t\tName\t\t\tBirthday\t\t\tStudent ID\t\t\tPhone number\n\n");
for (int i = 0; i < count; i++) {
printf("\t%d. %s\t\t\t\t%d/%d/%d\t\t\t%d\t\t\t0%d\n\n", i + 1, (s + i)->name, (s + i)->year, (s + i)->month, (s + i)->date, (s + i)->id, (s + i)->pnum);
}
printf("\t=========================================================================================\n\n");
}
void search(student* s) {
printf("\t=========================================Search==========================================\n\n");
printf("\t\tAvailable commands: \n");
printf("\t\t1. Search by name\t\t\t2. Search by ID\n\t\t3. Search by birthday\n");
printf("\t=========================================================================================\n\n");
printf("\t\tPlease choose command: ");
int com;
scanf("%d", &com);
switch (com) {
case 1: searchByName(s);
break;
case 2: searchByID(s);
break;
case 3: searchByBirthDate(s);
break;
}
}
void menu() {
printf("\n\t======================================MENU===============================================\n");
printf("\t\tAvailable commands: \n");
printf("\t\t1. Add Student\t\t\t2.Delete student\n\t\t3. Find student\t\t\t4. Table of all students\n");
printf("\t\t5. Transfer information from binary file\n\t\t6. Save information into binary file.\n\t\t0. Exit\n\n");
printf("\t=========================================================================================\n\n");
printf("\t\tPlease choose command: ");
}
int main() {
FILE* fp;
FILE* fpr;
printf("\t\tEnter a name of binary file that you want to create: ");
char filename[20];
scanf("%s", &filename);
strcat(filename, ".bin");
fp = fopen(filename, "ab");
if (fp == NULL) {
printf("\t\tUnable to open the file.\nError\n");
exit(1);
}
else printf("\t\t\tFile %s successfuly created\n\n", filename);
int iCount;
int n, c;
student* s;
printf("\t\tPlease enter number of students: ");
scanf("%d", &n);
printf("\n\n");
s = (student*)calloc(n, sizeof(student));
int quit = 1;
while (quit) {
menu();
scanf("%d", &c);
printf("\n");
switch (c) {
case 0:
quit = 0;
break;
case 1:
addInf(&s);
break;
case 2:
delInf(&s, n);
break;
case 3:
search(&s);
break;
case 4:
if (count == 0) printf("\t\tThere is no any given information yet.\n\n");
else printTable(&s);
break;
case 5:
printf("\t\tEnter a name or path of file that you want to open: ");
char readfilename[30];
scanf("%s", &readfilename);
strcat(readfilename, ".bin");
fpr = fopen(readfilename, "rb+");
if (fpr == NULL) {
printf("\t\tUnable to open the file.\nError\n");
break;
}
else printf("\t\tFile %s successfuly opened for reading\n", readfilename);
printf("\t\t\ttransfering binary data from %s into database\n", readfilename);
while ((fread(&s, sizeof(student), 1, fpr)) == 1) {
count++;
}
printf("\t\t%d student information was successfuly transferred\n", count);
break;
case 6:
iCount = fwrite(&s, sizeof(student), count, fp);
if (iCount != count) printf("Information could be missed in %s file\n", filename);
else printf("\t\tAll information was successfuly copied into %s file", filename);
}
sort(&s);
}
fclose(fp);
return 0;
}
First of all, enable warnings when compiling, and follow up on them!
This should tell you that &s is wrong in every place where you used it.
This causes your program to suffer from undefined behavior, which is a total pest when trying to debug your program!
Now then, on to the code that reads students from file:
while ((fread(s, sizeof(student), 1, fpr)) == 1) {
count++;
}
Every student is read into the same memory area (pointed to by s). They overwrite each other, leaving only the last one read. Try s + count instead of s:
while ((fread(s + count, sizeof(student), 1, fpr)) == 1) {
count++;
}

Why do I get a segmentation fault accessing a struct?

Edit: added the rest of my code so it's easier to see
I'm receiving a segmentation fault when trying to access certain values of a struct in a header file.
Here's courses.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "structs.h"
void createStudents () {
int random, i;
for (i = 0; i < 12; i++) {
students[i].firstName = firstName[i];
students[i].lastName = lastName[i];
random = 10000 + rand() % 89999;
students[i].num.studentNum = random;
printf("%d - %s, %s \n", students[i].num.studentNum, students[i].lastName, students[i].firstName);
}
}
void createCourses () {
int numbers[999];
int numbersLeft = 999;
char courseCode[512];
char courseCode1[512];
char courseCode2[512];
int numCourses = 3;
int random, i, j;
for (i = 0; i < 999; i++) {
numbers[i] = i;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode, sizeof courseCode, "CS00%d", random);
courses[0].cCode = courseCode;
}
else if (random < 100 && random > 9) {
snprintf(courseCode, sizeof courseCode, "CS0%d", random);
courses[0].cCode = courseCode;
}
else if (random > 99){
snprintf(courseCode, sizeof courseCode, "CS%d", random);
courses[0].cCode = courseCode;
}
courses[0].cName = courseName[0];
courses[0].cDescription = courseDescription[0];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[0].maxRegister = random;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode1, sizeof courseCode1, "CS00%d", random);
courses[1].cCode = courseCode1;
}
else if (random < 100 && random > 9) {
snprintf(courseCode1, sizeof courseCode1, "CS0%d", random);
courses[1].cCode = courseCode1;
}
else if (random > 99){
snprintf(courseCode1, sizeof courseCode1, "CS%d", random);
courses[1].cCode = courseCode1;
}
courses[1].cName = courseName[1];
courses[1].cDescription = courseDescription[1];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[1].maxRegister = random;
}
for (j = 0; j < 1; j++) {
random = rand() % numbersLeft;
if (random < 10) {
snprintf(courseCode2, sizeof courseCode2, "CS00%d", random);
courses[2].cCode = courseCode2;
}
else if (random < 100 && random > 9) {
snprintf(courseCode2, sizeof courseCode2, "CS0%d", random);
courses[2].cCode = courseCode2;
}
else if (random > 99){
snprintf(courseCode2, sizeof courseCode2, "CS%d", random);
courses[2].cCode = courseCode2;
}
courses[2].cName = courseName[2];
courses[2].cDescription = courseDescription[2];
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
random = 4 + rand() % 4;
courses[2].maxRegister = random;
}
}
void regiserStudents () {
int checkSum = 0, checkSum1 = 0, checkTemp = 0, count0 = 0, count1 = 0, count2 = 0;
int wCount0 = 0, wCount1 = 0, wCount2 = 0;
int v, i, j, random, max0, max1, max2;
max0 = courses[0].maxRegister;
max1 = courses[1].maxRegister;
max2 = courses[2].maxRegister;
for (i = 0; i < 2; i++) {
checkTemp = count0;
for (j = 0; j < 12; j++) {
random = rand() % 3;
if (random == 0) {
if (count0 == 0) {
courses[random].registered[count0] = &students[j];
count0++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[0].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count0 == max0) {
courses[random].waitlisted[count0] = &students[j];
wCount0++;
}
else {
courses[random].registered[count0] = &students[j];
count0++;
}
/*}*/
}
}
}
if (random == 1) {
if (count1 == 0) {
courses[random].registered[count1] = &students[j];
count1++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[1].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count1 == max1) {
courses[random].waitlisted[count1] = &students[j];
wCount1++;
}
else {
courses[random].registered[count1] = &students[j];
count1++;
}
}
}
}
if (random == 2) {
if (count2 == 0) {
courses[random].registered[count2] = &students[j];
count2++;
}
else {
checkSum1 = students[j].num.studentNum;
for (v = 0; v < checkTemp; v++) {
checkSum = courses[2].registered[v]->num.studentNum;
if (checkSum == checkSum1) {
/*Do Nothing*/
}
else if (count2 == max2) {
courses[random].waitlisted[count2] = &students[j];
wCount2++;
}
else {
courses[random].registered[count2] = &students[j];
count2++;
}
}
}
}
}
}
courses[0].studentRegistered = count0;
courses[1].studentRegistered = count1;
courses[2].studentRegistered = count2;
courses[0].studentWaitlisted = wCount0;
courses[1].studentWaitlisted = wCount1;
courses[2].studentWaitlisted = wCount2;
}
void printCourses () {
int i;
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[0].cCode, courses[0].cName, courses[0].cDescription, courses[0].studentRegistered, courses[0].maxRegister);
for (i = 0; i < courses[0].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[0].registered[i]->num.studentNum, courses[0].registered[i]->lastName, courses[0].registered[i]->firstName);
}
printf("Waitlisted Students (%d)", courses[0].studentWaitlisted);
if (courses[0].studentWaitlisted == 0) {
printf("\n");
}
else {
for (i = 0; i < courses[0].studentWaitlisted; i++) {
printf("* %d - %s, %s \n", courses[0].waitlisted[i]->num.studentNum, courses[0].waitlisted[i]->lastName, courses[0].waitlisted[i]->firstName);
}
}
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[1].cCode, courses[1].cName, courses[1].cDescription, courses[1].studentRegistered, courses[1].maxRegister);
for (i = 0; i < courses[1].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[1].registered[i]->num.studentNum, courses[1].registered[i]->lastName, courses[1].registered[i]->firstName);
}
printf("\n%s - %s: %s\nRegistered Students (%d/%d):\n", courses[2].cCode, courses[2].cName, courses[2].cDescription, courses[2].studentRegistered, courses[2].maxRegister);
for (i = 0; i < courses[2].studentRegistered; i++) {
printf("* %d - %s, %s \n", courses[2].registered[i]->num.studentNum, courses[2].registered[i]->lastName, courses[2].registered[i]->firstName);
}
}
And here's my header file
structs.h
#ifndef STRUCTS_H_
#define STRUCTS_H_
char *firstName[] = {
"Emma", "Liam", "Olivia",
"Noah", "Ava", "Logan",
"Sophia", "Lucas", "Isabella",
"Mason", "Shaylyn", "Jack"
};
char *lastName[] = {
"Smith", "Johnson", "Williams",
"Brown", "Jones", "Miller",
"Davis", "Garcia", "Rodriguez",
"Wilson", "Seguin", "Loveday"
};
typedef struct{
int studentNum;
}studentNumber;
typedef struct{
char *firstName;
char *lastName;
studentNumber num;
}studentID;
studentID students[12];
char *courseName[] = {"Web Programming", "Technical Communication", "Processor Architecture"};
char *courseDescription[] = {"Learn the language of HTML, and how to create websites.", "Learn the essentials of communication skills, and how to apply them on the job.", "Learn the basics of circuits and Machine Language coding."};
typedef struct {
int maxRegister;
char *cCode;
char *cName;
char *cDescription;
studentID *registered[8];
studentID *waitlisted[12];
int studentRegistered;
int studentWaitlisted;
}course;
course courses[3];
#endif
Printing the values of the registered students works fine, but when I print the waitlisted students I get a segmentation error. I used gdb and found it was on this line but couldn't figure out why:
printf("%d - %s, %s \n", courses[0].waitlisted[i]->num.studentNum, courses[0].waitlisted[i]->lastName, courses[0].waitlisted[i]->firstName);
studentID *waitlisted[12]; That means they will hold the address of variable of type structure studentID. You simply didn't do this but start to access those pointer variables. You have passed them to scanf which invokes undefined behavior due to trying to read an unintialized pointer variable.
So what you need to do here -
courses[i].waitlisted = malloc(sizeof *courses[i].waitlisted * courses[i].studentWaitlisted);
Same goes for the studentID also. Here fistName is a char* you need to allocate some meory to access it otherwise it's UB.
Or
typedef struct{
char firstName[100]; //you are considering that name length would be 100
//at max.
char lastName[100];
studentNumber num;
}studentID;
After OP edited question:
The seg fault you get is because of accessing a local variable after it's lifetime ended.
courses[0].cCode = courseCode;
What you can do is
courses[0].cCode = strdup(courseCode);
Initialize array int numbers[999]={0}; otherwise you might access garbage value as the indexing is result of random number geneartion.
if( random < 999){
numbers[random] = numbers[numbersLeft-1];
numbersLeft--;
}
else{
fprintf(stderr, "%s\n","Error" );
}
Lots of repeated code. You should remove repeated code. And also there is no need for single-iteration-for-loop.

How to format a number with thousands separator in C/C++

I am trying to do this simple task. Just to format a number using C or C++, but under Windows CE programming.
In this environment, neither inbue nor setlocale methods work.
Finally I did this with no success:
char szValue[10];
sprintf(szValue, "%'8d", iValue);
Any idea?
Here's one way - create a custom locale and imbue it with the appropriately customised facet:
#include <locale>
#include <iostream>
#include <memory>
struct separate_thousands : std::numpunct<char> {
char_type do_thousands_sep() const override { return ','; } // separate with commas
string_type do_grouping() const override { return "\3"; } // groups of 3 digit
};
int main()
{
int number = 123'456'789;
std::cout << "default locale: " << number << '\n';
auto thousands = std::make_unique<separate_thousands>();
std::cout.imbue(std::locale(std::cout.getloc(), thousands.release()));
std::cout << "locale with modified thousands: " << number << '\n';
}
expected output:
default locale: 123456789
locale with modified thousands: 123,456,789
I use this:
string thousands_separator(long long k, string symbol=",") {
int l, c, i;
string fin, s, u, rev;
bool min = false;
fin = "";
c = 0;
if(k < -999){
k *= -1;
min = true;
}
s = to_string(k);
if(k > 999){
l = s.length() - 1;
for (i = l; i >= 0; i--) {
fin += s[i];
c++;
if(c%3 == 0){
fin += symbol;
}
}
rev = fin;
fin = "";
l = rev.length() - 1;
for (i = l; i >= 0; i--) {
fin += rev[i];
}
u = fin[0];
if(u == symbol){
fin.erase(fin.begin());
}
if(min){
fin.insert(0, "-");
}
return fin;
} else {
return s;
}
}
Here's another way, using manual manipulations:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
int number = 123'456'789;
auto src = std::to_string(number);
auto dest = std::string();
auto count = 3;
for(auto i = src.crbegin() ; i != src.crend() ; ++i) {
if (count == 0)
{
dest.push_back(',');
count = 3;
}
if (count--) {
dest.push_back(*i);
}
}
std::reverse(dest.begin(), dest.end());
std::cout << dest << '\n';
}
Finally, I have developed my own function:
std::string CFormat::GetInteger(int iValue)
{
std::string sValue;
std::string sDot = ".";
for(int iTmp = iValue; iTmp; iTmp /= 1000)
{
if ((int)(iTmp / 1000) == 0)
sDot.clear();
sValue = sDot + SSTR(iTmp % 1000) + sValue;
}
if (sValue.empty())
sValue = "0";
return sValue;
}
I think it's simpler and it does not depend on other classes other than std::string, which I know it will work in Windows Mobile device.
Why re-invent the wheel and not use functions that are provided for this? See GetNumberFormat.
Custom formatting can be done using the correct NUMBERFMT structure values. For example (pseudo-code):
//Display three digits after the decimal point.
.NumDigits = 3
//Display zeros after the decimal point.
.LeadingZero = 1
//Group every three digits to the left of the decimal.
.Grouping = 3
//Use a comma to as the decimal point (like they do in France and Spain).
.lpDecimalSep = ","
//Likewise, use a period as the grouping separator.
.lpThousandSep = "."
//Put the negative sign immediately after the number.
.NegativeOrder = 3
These functions work in C++, for numbers in string, with or without decimals.
Next function not support negative string numbers or decimal separators, but it was very simple:
std::string quickAddThousandSeparators(std::string value, char thousandSep = ',')
{
int len = value.length();
int dlen = 3;
while (len > dlen) {
value.insert(len - dlen, 1, thousandSep);
dlen += 4;
len += 1;
}
return value;
}
Next function support negative string numbers and decimal separators:
std::string addThousandSeparators(std::string value, char thousandSep = ',', char decimalSep = '.', char sourceDecimalSep = '.')
{
int len = value.length();
int negative = ((len && value[0] == '-') ? 1: 0);
int dpos = value.find_last_of(sourceDecimalSep);
int dlen = 3 + (dpos == std::string::npos ? 0 : (len - dpos));
if (dpos != std::string::npos && decimalSep != sourceDecimalSep) {
value[dpos] = decimalSep;
}
while ((len - negative) > dlen) {
value.insert(len - dlen, 1, thousandSep);
dlen += 4;
len += 1;
}
return value;
}
And gtest passed tests:
TEST (quickAddThousandSeparators, basicNumbers) {
EXPECT_EQ("", quickAddThousandSeparators(""));
EXPECT_EQ("1", quickAddThousandSeparators("1"));
EXPECT_EQ("100", quickAddThousandSeparators("100"));
EXPECT_EQ("1,000", quickAddThousandSeparators("1000"));
EXPECT_EQ("10,000", quickAddThousandSeparators("10000"));
EXPECT_EQ("100,000", quickAddThousandSeparators("100000"));
EXPECT_EQ("1,000,000", quickAddThousandSeparators("1000000"));
EXPECT_EQ("1,000,000,000", quickAddThousandSeparators("1000000000"));
EXPECT_EQ("1,012,789,345,456,123,678,456,345,809", quickAddThousandSeparators("1012789345456123678456345809"));
}
TEST (quickAddThousandSeparators, changeThousandSeparator) {
EXPECT_EQ("", quickAddThousandSeparators("",'.'));
EXPECT_EQ("1", quickAddThousandSeparators("1",'.'));
EXPECT_EQ("100", quickAddThousandSeparators("100", '.'));
EXPECT_EQ("1.000", quickAddThousandSeparators("1000", '.'));
EXPECT_EQ("1.000.000.000", quickAddThousandSeparators("1000000000", '.'));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809", quickAddThousandSeparators("1012789345456123678456345809", '.'));
}
TEST (addThousandSeparators, basicNumbers) {
EXPECT_EQ("", addThousandSeparators(""));
EXPECT_EQ("1", addThousandSeparators("1"));
EXPECT_EQ("100", addThousandSeparators("100"));
EXPECT_EQ("1,000", addThousandSeparators("1000"));
EXPECT_EQ("10,000", addThousandSeparators("10000"));
EXPECT_EQ("100,000", addThousandSeparators("100000"));
EXPECT_EQ("1,000,000", addThousandSeparators("1000000"));
EXPECT_EQ("1,000,000,000", addThousandSeparators("1000000000"));
EXPECT_EQ("1,012,789,345,456,123,678,456,345,809", addThousandSeparators("1012789345456123678456345809"));
}
TEST (addThousandSeparators, negativeBasicNumbers) {
EXPECT_EQ("", addThousandSeparators(""));
EXPECT_EQ("-1", addThousandSeparators("-1"));
EXPECT_EQ("-100", addThousandSeparators("-100"));
EXPECT_EQ("-1,000", addThousandSeparators("-1000"));
EXPECT_EQ("-10,000", addThousandSeparators("-10000"));
EXPECT_EQ("-100,000", addThousandSeparators("-100000"));
EXPECT_EQ("-1,000,000", addThousandSeparators("-1000000"));
EXPECT_EQ("-1,000,000,000", addThousandSeparators("-1000000000"));
EXPECT_EQ("-1,012,789,345,456,123,678,456,345,809", addThousandSeparators("-1012789345456123678456345809"));
}
TEST (addThousandSeparators, changeThousandSeparator) {
EXPECT_EQ("", addThousandSeparators("",'.'));
EXPECT_EQ("-1", addThousandSeparators("-1",'.'));
EXPECT_EQ("100", addThousandSeparators("100", '.'));
EXPECT_EQ("-1.000", addThousandSeparators("-1000", '.'));
EXPECT_EQ("-1.000.000.000", addThousandSeparators("-1000000000", '.'));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809", addThousandSeparators("1012789345456123678456345809", '.'));
}
TEST (addThousandSeparators, changeDecimalSeparator) {
EXPECT_EQ("0,5", addThousandSeparators("0.5",'.',','));
EXPECT_EQ("0", addThousandSeparators("0",'.',','));
EXPECT_EQ("-1,23", addThousandSeparators("-1.23",'.',','));
EXPECT_EQ("100,56", addThousandSeparators("100.56", '.',','));
EXPECT_EQ("-1.000,786", addThousandSeparators("-1000.786", '.',','));
EXPECT_EQ("-1.000.000.000,4859", addThousandSeparators("-1000000000.4859", '.', ','));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809,6785960", addThousandSeparators("1012789345456123678456345809.6785960", '.',','));
}
TEST (addThousandSeparators, changeSourceDecimalSeparator) {
EXPECT_EQ("0,5", addThousandSeparators("0,5",'.',',',','));
EXPECT_EQ("0", addThousandSeparators("0",'.',',',','));
EXPECT_EQ("-1,23", addThousandSeparators("-1,23",'.',',',','));
EXPECT_EQ("100,56", addThousandSeparators("100,56", '.',',',','));
EXPECT_EQ("-1.000,786", addThousandSeparators("-1000,786", '.',',',','));
EXPECT_EQ("-1.000.000.000,4859", addThousandSeparators("-1000000000,4859", '.', ',',','));
EXPECT_EQ("1.012.789.345.456.123.678.456.345.809,6785960", addThousandSeparators("1012789345456123678456345809,6785960", '.',',',','));
}
Note: At the time this answer was submitted, the post was tagged C/C++. Now it is tagged C. I suspect it may change again.
Should you want to roll your own C solution which uses C99, the below forms the basis that works on my Windows gcc under various locales.
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#define INT_STR_SIZE (CHAR_BIT*sizeof(int)*3/10 + 2)
#define INT_SEP_STR_SIZE (INT_STR_SIZE * 3/2 + 1)
#define INT_SEP(x) int_sep((char[INT_SEP_STR_SIZE]) { "" }, INT_SEP_STR_SIZE, x)
char *int_sep(char *s, size_t sz, int x) {
struct lconv *locale_ptr = localeconv();
const char *grouping = locale_ptr->grouping;
char sep = locale_ptr->thousands_sep[0];
if (sz > 0) {
int x0 = x;
char *ptr = s + sz;
*--ptr = '\0';
char count = 0;
do {
if (count >= grouping[0]) {
*--ptr = sep;
if (grouping[1]) grouping++;
count = 0;
}
count++;
//printf("%d %d <%s> %p\n", count, n, locale_ptr->grouping, (void*)locale_ptr);
*--ptr = (char) (abs(x % 10) + '0');
} while (x /= 10);
if (x0 < 0) {
*--ptr = '-';
}
memmove(s, ptr, (size_t) (&s[sz] - ptr));
}
return s;
}
main
int main(void) {
puts(setlocale(LC_ALL,"en_US"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_SEP_STR_SIZE), INT_SEP(12345678), INT_SEP(1234));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(-1), INT_SEP(0), INT_SEP(1));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"C"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"it_IT"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"as_IN"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
puts(setlocale(LC_ALL,"be_BY"));
printf(":%15s: :%15s: :%15s:\n", INT_SEP(INT_MIN), INT_SEP(INT_MIN+1), INT_SEP(INT_MAX));
return 0;
}
Output
en_US
: 17: : 12,345,678: : 1,234:
: -1: : 0: : 1:
: -2,147,483,648: : -2,147,483,647: : 2,147,483,647:
C
: -2147483648: : -2147483647: : 2147483647:
it_IT
: -2.147.483.648: : -2.147.483.647: : 2.147.483.647:
as_IN
:-2,14,74,83,648: :-2,14,74,83,647: : 2,14,74,83,647:
be_BY
: -2 147 483 648: : -2 147 483 647: : 2 147 483 647:

Removing Garbage value in array in C

I have a garbage problem in my array in C, that I can't solve and I have used the memset function for this but this is not useful to me. how can I solve this problem. If I run this code in Code Block or other PC then this is not run completely.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
int main() {
clrscr();
int a, b, len = 0, x, i = 0, j, match, misMatch, gapPenalty, sim, m1, m2, m3;
char ch;
char *seq1 = (char *)malloc(100 * sizeof(char));
char *seq2 = (char *)malloc(100 * sizeof(char));
char *s1 = (char *)malloc(100 * sizeof(char));
char *s2 = (char *)malloc(100 * sizeof(char));
/*memset(seq1, 0, strlen(seq1) - 1);
memset(seq2, 0, strlen(seq2) - 1);
memset(s1, 0, strlen(s1) - 1);
memset(s2, 0, strlen(s2) - 1);*/
int **matrix;
int **back;
FILE *inputFile;
inputFile = fopen("in.txt", "r");
printf("Enter Match Point : ");
scanf("%d", &match);
printf("Enter Mismatch Point : ");
scanf("%d", &misMatch);
printf("Enter Gap Point : ");
scanf("%d", &gapPenalty);
while (fscanf(inputFile,"%s\n%s", seq1, seq2) != EOF);
a = strlen(seq1);
b = strlen(seq2);
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
if (i == 0 || j == 0) {
if (i == 0) {
matrix[j][i] = j * gapPenalty;
back[j][i] = 0;
}
if (j == 0) {
matrix[j][i] = i * gapPenalty;
back[j][i] = 0;
}
} else {
if (seq1[i - 1] == seq2[j - 1]) {
sim = match;
} else {
sim = misMatch;
}
m1 = matrix[j - 1][i - 1] + sim;
m2 = matrix[j - 1][i] + gapPenalty;
m3 = matrix[j][i - 1] + gapPenalty;
if (m1 > m2) {
if (m1 > m3) {
matrix[j][i] = m1;
back[j][i] = 1;
} else {
matrix[j][i] = m3;
back[j][i] = 3;
}
} else {
if (m2 > m3) {
matrix[j][i] = m2;
back[j][i] = 2;
} else {
matrix[j][i] = m3;
back[j][i] = 3;
}
}
}
}
}
printf("%s", seq1);
printf("\n");
printf("%s", seq2);
printf("\n");
if (a > b) {
len = a;
} else {
len = b;
}
for (x = 0; x < len; x++) {
if (back[b][a] == 1) {
s1[x] = seq1[a - 1];
s2[x] = seq2[b - 1];
a = a - 1;
b = b - 1;
} else if(back[b][a] == 2) {
s1[x] = seq1[a - 1];
s2[x] = '-';
a = a - 1;
} else {
s1[x] = '-';
s2[x] = seq2[b - 1];
b = b - 1;
}
}
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
printf("%d ", matrix[j][i]);
}
printf("\n");
}
printf("\n");
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
printf("%d ", back[j][i]);
}
printf("\n");
}
printf("\n");
printf("%s", s1);
printf("\n");
printf("%s", s2);
printf("\n");
free(s1);
free(s2);
free(matrix);
free(back);
getch();
return 0;
}
Use calloc(). calloc() initializes all the allocated memory to 0.
// sizeof (char), by definition, is 1
char *seq1 = calloc(100, 1);
char *seq2 = calloc(100, 1);
char *s1 = calloc(100, 1);
char *s2 = calloc(100, 1);
The immediate problem with your commented code is that you cannot apply strlen() to an uninitialized array. You should be using the correct size (which you just used a few statements before) instead
/*memset(seq1, 0, 100);
memset(seq2, 0, 100);
memset(s1, 0, 100);
memset(s2, 0, 100);*/

Resources