Question about Compare with String and Integer. CS50 Pset 4 - string

I am studying CS50 Pset 4.
As I know, I type the same word eg: "Emma". When I compare them, they will not the same coz they are storing it in 2 different addresses in the memory.
But I am confused about integer, they are also storing in 2 different addresses in the memory even I input the same number. But they are the same when I compare them.
Can someone tell me what I misunderstood?
#include <stdio.h>
#include <cs50.h>
int main(void)
{
int i = get_int("i: ");
int j = get_int("j: ");
char *s = get_string("s: ");
char *t = get_string("t: ");
if (i == j)
{
printf("Same\n");
printf("%p\n", &i);
printf("%p\n", &j);
}
else
{
printf("Different\n");
printf("%p\n", &i);
printf("%p\n", &j);
}
if (s == t)
{
printf("Same\n");
printf("%p\n", &s);
printf("%p\n", &t);
}
else
{
printf("Different\n");
printf("%p\n", &s);
printf("%p\n", &t);
}
}

You can't compare two strings using ==. In order to do so sucessfully, you either use a function called strcmp, or create a loop iterating over all characters in the string. (include #include <string.h> in order to make this work. This is what your code should look like:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
int i = get_int("i: ");
int j = get_int("j: ");
char *s = get_string("s: ");
char *t = get_string("t: ");
if (i == j)
{
printf("Same\n");
printf("%p\n", &i);
printf("%p\n", &j);
}
else
{
printf("Different\n");
printf("%p\n", &i);
printf("%p\n", &j);
}
if (strcmp(s, t) == 0)
{
printf("Same\n");
printf("%p\n", &s);
printf("%p\n", &t);
}
else
{
printf("Different\n");
printf("%p\n", &s);
printf("%p\n", &t);
}
}
strcmp takes input two string, and outputs 0 if they're the same, and any other number if not. (Hope this helps!!:))

Related

How do I create a mutex with two condvars?

I want to build a single-producer multiple-consumer example in Rust, where the producer is bounded to have no more than 10 outstanding items. I modeled a solution in C that uses a a mutex and two condvars. One condvar is to wait the consumers when there is nothing to consume and one condvar is to wait for the producer when the unconsumed items count is greater than say 10. The C code is below.
As I understand it from the Rust docs, there must be a 1-1 connection between std::sync::Mutex and a std::sync::Condvar so I can't make an exact translation of my C solution.
Is there some other way to achieve the same end (that I cannot see) in Rust using std::sync::Mutex and std::sync::Condvar.
#define _GNU_SOURCE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
//
// This is a simple example of using a mutex and 2 condition variables to
// sync a single writer and multiple readers interacting with a bounded (fixed max size) queue
//
// in this toy example a queue is simulated by an int counter n_resource
//
int n_resource;
pthread_cond_t rdr_cvar;
pthread_cond_t wrtr_cvar;
pthread_mutex_t mutex;
void reader(void* data)
{
long id = (long)data;
for(;;) {
pthread_mutex_lock(&mutex);
while (n_resource <= 0) {
pthread_cond_wait(&rdr_cvar, &mutex);
}
printf("Reader %ld n_resource = %d\n", id, n_resource);
--n_resource;
// if there are still things to read - singla one reader
if(n_resource > 0) {
pthread_cond_signal(&rdr_cvar);
}
// if there is space for the writer to add another signal the writer
if(n_resource < 10) {
pthread_cond_signal(&wrtr_cvar);
}
pthread_mutex_unlock(&mutex);
}
}
void writer(void* data)
{
for(;;) {
pthread_mutex_lock(&mutex);
printf("Writer before while n_resource %d \n", n_resource);
while (n_resource > 10) {
pthread_cond_wait(&wrtr_cvar, &mutex);
}
printf("Writer after while n_resource %d \n", n_resource);
++n_resource;
// if there is something for a reader to read signal one of the readers.
if(n_resource > 0) {
pthread_cond_signal(&rdr_cvar);
}
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t rdr_thread_1;
pthread_t rdr_thread_2;
pthread_t wrtr_thread;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&rdr_cvar, NULL);
pthread_cond_init(&wrtr_cvar, NULL);
pthread_create(&rdr_thread_1, NULL, &reader, (void*)1L);
pthread_create(&rdr_thread_2, NULL, &reader, (void*)2L);
pthread_create(&wrtr_thread, NULL, &writer, NULL);
pthread_join(wrtr_thread, NULL);
pthread_join(rdr_thread_1, NULL);
pthread_join(rdr_thread_2, NULL);
}
While a CondVar needs to be associated with only one Mutex, it is not necessary that a Mutex is associated with only one CondVar.
For example, the following code seems to work just fine - you can run it on the playground.
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
struct Q {
rdr_cvar: Condvar,
wrtr_cvar: Condvar,
mutex: Mutex<i32>,
}
impl Q {
pub fn new() -> Q {
Q {
rdr_cvar: Condvar::new(),
wrtr_cvar: Condvar::new(),
mutex: Mutex::new(0),
}
}
}
fn writer(id: i32, qq: Arc<Q>) {
let q = &*qq;
for i in 0..10 {
let guard = q.mutex.lock().unwrap();
let mut guard = q.wrtr_cvar.wait_while(guard, |n| *n > 3).unwrap();
println!("{}: Writer {} n_resource = {}\n", i, id, *guard);
*guard += 1;
if *guard > 0 {
q.rdr_cvar.notify_one();
}
if *guard < 10 {
q.wrtr_cvar.notify_one();
}
}
}
fn reader(id: i32, qq: Arc<Q>) {
let q = &*qq;
for i in 0..10 {
let guard = q.mutex.lock().unwrap();
let mut guard = q.rdr_cvar.wait_while(guard, |n| *n <= 0).unwrap();
println!("{} Reader {} n_resource = {}\n", i, id, *guard);
*guard -= 1;
if *guard > 0 {
q.rdr_cvar.notify_one();
}
if *guard < 10 {
q.wrtr_cvar.notify_one();
}
}
}
fn main() {
let data = Arc::new(Q::new());
let data2 = data.clone();
let t1 = thread::spawn(move || writer(0, data2));
let t2 = thread::spawn(move || reader(1, data));
t1.join().unwrap();
t2.join().unwrap();
}

change value of struct inside a struct

The secondexample below is what I would like to achieve in the firstcode written up. I want to ask how many 'dati' wants to insert then I have to do a malloc and I want to ask and save each dato of every struct so, firstly cdfM of the struct maestra and so on... How can I do that? How should I create the array with the malloc and how what should I do to save all the infos?
thx
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
struct dati{
struct maestra{
char cdfM[MAX];
char nomeM[MAX];
char cognomeM[MAX];
char specializzazioneM[MAX];
}
struct classe{
int id;
char nome[MAX];
char colore[MAX];
}
struct insegnamento{
int idclasseI;
char cfmaestra[MAX];
}
struct bambino{
char cdfB[MAX];
char nomeB[MAX];
char cognomeB[MAX];
char dataNascita[MAX];
int idclasseB;
char dataIscrizione[MAX];
}
}
int main () {
struct dati *p,*q,*r,*s;
struct maestra **p;
struct classe **q;
struct insegnamento **r;
struct bambino **s;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
struct studente{
char nomeCognome[MAX];
int numeroMatricola;
float percentualeEP;
};
int main() {
struct studente *p;
int m, i;
printf("Quanti studenti devi inserire: \n");
scanf("%d", &m);
p = malloc(m*sizeof(int));
for (i=0; i < m; i++){
printf("Inserisci i dati dell'utente numero %d\n",i+1);
printf("Inserisci il nome cognome: \n");
scanf(" ");
fgets((p+i)->nomeCognome, MAX, stdin);
printf("Inserisci la matricola: \n");
scanf("%d",&(p+i)->numeroMatricola);
printf("Inserisci la percentuale di esami passati: \n");
scanf("%f", &(p+i)->percentualeEP);
}

How to compile intrinsic code in gcc

I am trying to compile this code:
#include <sys/types.h>
#include <argp.h>
#include <stdlib.h>
#include <xmmintrin.h>
__attribute__((noinline)) void vadd(float *a, float *b, size_t size)
{
size_t i;
for (i=0; i<size; i+=4)
{
__m128 v1 = _mm_load_ps(a + i); //loads up 4 floats into a __m128
__m128 v2 = _mm_load_ps(b + i); //loads up 4 floats into a __m128
__m128 v3 = _mm_add_ps(v1, v2);
_mm_store_ps(a+i, v3);
}
}
__attribute__((noinline)) void sadd(float *a, float *b, size_t size)
{
size_t i;
for(i=0; i<size; i++)
{
a[i] += b[i];
}
}
int main (void)
{
size_t size = 300000000;
float *a = (float *)calloc(size, sizeof(float));
float *b = (float *)calloc(size, sizeof(float));
vadd(a, b, size);
sadd(a, b, size);
}
I am receiving this error:
/usr/lib/gcc/i486-linux-gnu/4.8/include/mmintrin.h: In function ‘_mm_cvtsi32_si64’:
/usr/lib/gcc/i486-linux-gnu/4.8/include/mmintrin.h:61:3: error: can’t convert between vector values of different size
return (__m64) __builtin_ia32_vec_init_v2si (__i, 0);
Is there a way to work that out?

How to create thunk in x64?

I've found nice example how to create thunk for closure, but it's 32-bit version:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
struct env {
int x;
};
struct __attribute__((packed)) thunk {
unsigned char push;
struct env * env_addr;
unsigned char call;
signed long call_offset;
unsigned char add_esp[3];
unsigned char ret;
};
struct thunk default_thunk = {0x68, 0, 0xe8, 0, {0x83, 0xc4, 0x04}, 0xc3};
typedef void (* cfunc)();
struct thunk * make_thunk(struct env * env, void * code)
{
struct thunk * thunk = (struct thunk *)mmap(0,sizeof(struct thunk), PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
*thunk = default_thunk;
thunk->env_addr = env;
thunk->call_offset = code - (void *)&thunk->add_esp[0]; // Pretty!
mprotect(thunk,sizeof(struct thunk), PROT_EXEC);
return thunk;
}
void block(struct env * env) {
env->x += 1;
printf ("block: x is %d\n", env->x);
}
cfunc foo (int x)
{
struct env * env = (struct env *)malloc(sizeof(struct env));
env->x = x;
printf ("x is %d\n",env->x);
return (cfunc)make_thunk(env,(void *)&block);
}
int main() {
cfunc c = foo(5);
c();
c();
}
How can I rewrite it for 64-bit version?
I'm using Linux x86_64. I've been able to cross-compile it with gcc -m32, which worked perfectly.
The code below is designed to be used with GCC on Linux and should support 32 and 64 bit compilation.
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
struct env {
int x;
};
#if __x86_64__
struct __attribute__((packed)) thunk {
unsigned char mov[2];
struct env * env_addr;
unsigned char movrax[2];
void (*call_address)();
unsigned char jmp[2];
};
struct thunk default_thunk = {{0x48, 0xbf}, 0x0, {0x48, 0xb8}, 0x0, {0xff, 0xe0} };
#elif __i386__
struct __attribute__((packed)) thunk {
unsigned char push;
struct env * env_addr;
unsigned char call;
signed long call_offset;
unsigned char add_esp[3];
unsigned char ret;
};
struct thunk default_thunk = {0x68, 0, 0xe8, 0, {0x83, 0xc4, 0x04}, 0xc3};
#else
#error Architecture unsupported
#endif
typedef void (* cfunc)();
struct thunk * make_thunk(struct env * env, void * code)
{
struct thunk * thunk = (struct thunk *)mmap(0,sizeof(struct thunk),
PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
*thunk = default_thunk;
#if __x86_64__
thunk->env_addr = env;
thunk->call_address = code; /* Pretty! */
#else
thunk->env_addr = env;
thunk->call_offset = code - (void *)&thunk->add_esp[0]; /* Pretty! */
#endif
mprotect(thunk,sizeof(struct thunk), PROT_EXEC);
return thunk;
}
void block(struct env * env) {
env->x += 1;
printf ("block: x is %d\n", env->x);
}
cfunc foo (int x)
{
struct env * env = (struct env *)malloc(sizeof(struct env));
env->x = x;
printf ("x is %d\n",env->x);
return (cfunc)make_thunk(env,(void *)&block);
}
int main() {
cfunc c = foo(5);
c();
c();
return 0;
}
Assuming that the OS is using System V 64bit ABI (Which Linux uses) calling convention then the first parameter that will be passed to the function will be in register %rdi. Then we just have to mov the environment address (env_addr) to %rdi and then do a call. The call uses an indirect jump to an absolute location through %rax. So the instruction sequence looks like (at&t syntax):
mov $env_addr, %rdi
movabs $call_pointer, %rax
jmpq *%rax # Tail call instead of call/retq

Changing a struct value within a function with c++

I wanted to create a quick quadtree in c++ but found that when I change a value of a struct within a function the value reverts. Also within the recursive function I wont some of the data created to be global. How do I do this?
#include <iostream>
struct a{
unsigned int value;
struct a * leaf[4];
};
void build(struct a root, unsigned int depth){
depth++;
root.value = 0;
struct a leaf0;
root.leaf[0] = &leaf0;
struct a leaf1;
root.leaf[1] = &leaf1;
struct a leaf2;
root.leaf[2] = &leaf2;
struct a leaf3;
root.leaf[3] = &leaf3;
if (depth != 5) {
build(*root.leaf[0], depth);
build(*root.leaf[1], depth);
build(*root.leaf[2], depth);
build(*root.leaf[3], depth);
}
}
int main(int argc, const char * argv[])
{
struct a root;
root.value = 364;
build(root, 0);
std::cout << root.value;
return 0;
}
You must pass the address of the struct to your function (which should accept a pointer to the struct):
void build(struct a *root, unsigned int depth) {
...
}
int main(int argc, const char * argv[])
...
build(&root, 0);
}

Resources