问:
Curly braces around a parameter in Angular
Looking at some Angular code:

    @Component({
      selector: 'my-app',
      templateUrl: 'kendoGrid.component.html'
    })
    export class AppComponent implements OnInit {

        public editDataItem: Product;
        public isNew: boolean;
        private editService: EditService;

        public editHandler({dataItem}) { // What does wrapping a parameter in curly braces do?
            this.editDataItem = dataItem;
            this.isNew = false;
        }
    }
```

I could not find much result when I try to google curly braces / moustache with parameter in the context of Angular. What effect is achieved by wrapping a parameter in curly braces in Angular?

Thanks.

答:
It's known as destructuring, and it works like so:

Say you have an object which contains a person's name and age:

```<code>const person = {
    name: "John Doe",
    age: 42
};
</code>```

And you have a function which prints out the age of the object passed to it:

```<code>function printAge(obj) {
    console.log(obj.age);
}
</code>```

This function uses the whole object - however, since we don't actually need the other properties of the object (only age) we can use destructuring to extract that property:

```<code>function printAge({ age }) {
    console.log(age);
}
</code>```

This is ES6 shorthand for the following:

```<code>function printAge(obj) {
    var age = obj.age;
    console.log(age);
}
</code>```

So, all that this function does:

```<code>public editHandler({ dataItem }) {
    this.editDataItem = dataItem;
    this.isNew = false;
}
</code>```

Is this ES5:

```<code>public editHandler(item) {
    var dataItem = item.dataItem;
    this.editDataItem = dataItem;
    this.isNew = false;
}
</code>```

Body:
Looking at some Angular code:

    @Component({
      selector: 'my-app',
      templateUrl: 'kendoGrid.component.html'
    })
    export class AppComponent implements OnInit {

        public editDataItem: Product;
        public isNew: boolean;
        private editService: EditService;

        public editHandler({dataItem}) { // What does wrapping a parameter in curly braces do?
            this.editDataItem = dataItem;
            this.isNew = false;
        }
    }

I could not find much result when I try to google curly braces / moustache with parameter in the context of Angular. What effect is achieved by wrapping a parameter in curly braces in Angular?

Thanks.

Body:
It's known as destructuring, and it works like so:

Say you have an object which contains a person's name and age:

const person = {
    name: "John Doe",
    age: 42
};

And you have a function which prints out the age of the object passed to it:

function printAge(obj) {
    console.log(obj.age);
}

This function uses the whole object - however, since we don't actually need the other properties of the object (only age) we can use destructuring to extract that property:

function printAge({ age }) {
    console.log(age);
}

This is ES6 shorthand for the following:

function printAge(obj) {
    var age = obj.age;
    console.log(age);
}

So, all that this function does:

public editHandler({ dataItem }) {
    this.editDataItem = dataItem;
    this.isNew = false;
}

Is this ES5:

public editHandler(item) {
    var dataItem = item.dataItem;
    this.editDataItem = dataItem;
    this.isNew = false;
}


来源: stackexchange

问:
Logic problem in C. Define number of interactions on pthreads
So i have these code, i want to define my number of interactions manualy, so for each thread basicaly i define lets say 10 interactios so each thread will compute a block of 10. If i do that the thread wont go after the first 10.

Basically what i want is evrytime a thread finishes computing 10 interactions goes and does another block of ten, lets say the 100 in 10 interactions have 10 blocks i want for example 4 threads working each one computes a block when finishing goes and grab another block

Can anyone help?

```<code>#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NTHREADS      4
#define ARRAYSIZE   1000000
#define ITERATIONS   ARRAYSIZE / NTHREADS

double  sum=0.0, a[ARRAYSIZE];
pthread_mutex_t sum_mutex;

void *do_work(void *tid)
{
  int i, start, *mytid, end;
  double mysum=0.0;

  /* Initialize my part of the global array and keep local sum */
  mytid = (int *) tid;
  start = (*mytid * ITERATIONS);
  end = start + ITERATIONS;
  printf ("Thread %d doing iterations %d to %d\n",*mytid,start,end-1);
  for (i=start; i < end ; i++) {
    a[i] = i * 1.0;
    mysum = mysum + a[i];
    }

  /* Lock the mutex and update the global sum, then exit */
  pthread_mutex_lock (&sum_mutex);
  sum = sum + mysum;
  pthread_mutex_unlock (&sum_mutex);
  pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  int i, start, tids[NTHREADS];
  pthread_t threads[NTHREADS];
  pthread_attr_t attr;

  /* Pthreads setup: initialize mutex and explicitly create threads in a
     joinable state (for portability).  Pass each thread its loop offset */
  pthread_mutex_init(&sum_mutex, NULL);
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  for (i=0; i<NTHREADS; i++) {
    tids[i] = i;
    pthread_create(&threads[i], &attr, do_work, (void *) &tids[i]);
    }

  /* Wait for all threads to complete then print global sum */
  for (i=0; i<NTHREADS; i++) {
    pthread_join(threads[i], NULL);
  }
  printf ("Done. Sum= %e \n", sum);

  sum=0.0;
  for (i=0;i<ARRAYSIZE;i++){
  a[i] = i*1.0;
  sum = sum + a[i]; }
  printf("Check Sum= %e\n",sum);

  /* Clean up and exit */
  pthread_attr_destroy(&attr);
  pthread_mutex_destroy(&sum_mutex);
  pthread_exit (NULL);
}
</code>```

I have tried inumerous aways but cant get the logic to do that. Maybe a while loop inside the void?? anay ideas?

答:
So,here is the problem solved for the ones that are intrested.</p>

```<code>#include <pthread.h>    //utilizado para as pthreads
#include <stdio.h>      //utilizado para os printf
#include <stdlib.h>     //utilizado para o malloc

int nt,n,nbloco;                                                                        // defenição das variáveis base pedidas
int resultado_esperado = 0, *matriz, *buffer,sinal_saida,soma_global, items_buffer=0;   //defenição das variaveis udadas para calculo e controlo do programa

pthread_mutex_t indice_mutex, criacao_thread_mutex,buffer_mutex,soma_final_mutex;       // defenição dos mutex para exclusividade, poderia ser usado um so mutex para garantir que nao exista confusoes de desbloqueio opteou-se por criacao de mutex exclusivos para as operacoes

//CASO USE O PROGRAMA COM A FUNCAO SCHED YIELD
//DESATIVAR AS CONDICOES PRODUZIR E CONSUMIR

pthread_cond_t cond/*, produzir, consumir*/;                                                // defenição de condições para sinalizar threads criadas e sinalizaao de buffer cheio (mais rapido do que usar o sched_yield as duas opcoes estao acessiveis)

static int numero_para_comeco = 0;                                                      //numero de controlo para saber que bloco a thread vai processar

typedef struct {

    //esta estrutara vai passar os valores para as threads
    //valores que vão diferir de uma thread para
    //a outra, dái se encontrarem dentro da estrutura.

  int inicio_inicial;
  int id_threads;

}estrutura_geral;

// esta primeira função representa a função das tarefas
// calculadoras está dividida em duas partes um primeira
//que processa o bloco associado de inicio conforme a sequencia de numero de ordem
//(cada thread obriagtoriamento computa um bloco)
// e uma segunda que permite qualquer thread agarrar um novo bloco
// esta funç]ao tem um apontador que direciona para a estrutura

void *calculadoras(void *es)
{
        int i, inicio, fim, contador;                                           //defenicao de variaveis
        int calculo_parcial = 0;                                    //defenicao variavel soma parcial

        pthread_mutex_lock(&criacao_thread_mutex);                  //bloqueio do mutex para garantir a leitura da estrutura e o envio de sinal da thread criada

        estrutura_geral * const estrutura = es;                     //pointer é criado para a estrutura

        int const id_threads = estrutura->id_threads;               //leitura dos elemnetos da estrutura
        int const inicio_inicial = estrutura->inicio_inicial;

        contador=0;                                                 //incializaçao do conatdor

        if ((inicio_inicial+nbloco) < n){                           //verificaçao do tamanho do bloco a calcular
            fim = inicio_inicial + nbloco;
        }else{
            fim = n;
        }

        pthread_cond_signal(&cond);                                 //sinalizacao à main thread que a thread foi criada

        pthread_mutex_unlock(&criacao_thread_mutex);                //desbloqueio do mutex para a variavel de condicao na main thread ser usada

        sched_yield();                                              //nao é necessário estar aqui mas ao fazer garanto que outras threads tenham ainda mais oportunidade.

        //printf ("A thread %d está a calcular o bloco de %d a %d\n", id_threads, inicio_inicial+1, fim);

        //primeira parte da computacao onde os valores para
        //soma passados orbriatoriamente por oredem de criacao da thread

                //pthread_mutex_lock (&buffer_mutex);                   //(quando usar as condiçoes ou fazer o calculo do bloco completo)estamos a entrar numa regiao onde a computacao vai ser feira precisamos de boquea o mutex para que nao exista perda de dados

                 while(items_buffer==nt){

                 //enquanto o buffer for igual ao numero de tarefas
                 //existem duas opçoes ou a thread manda um sinal à thread que
                 //soma os valores do buffer para limpar o buffer
                 //ou entao podemos optar por nao mandar o sinal desbloquear o mutex
                 // e simplesmente libertar a tarefa com sched_yield
                 //o sinal acaba por se mais eficaz pois nao e certo que com o sched yield
                 //a proxima tarefa seja a somadora

                            //pthread_cond_wait(&produzir,&buffer_mutex);
                            //pthread_mutex_unlock(&buffer_mutex);              //ativar quando o mutex for bloqueado anteriormente
                            sched_yield();                                      //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
                        }

                    for (i = inicio_inicial; i < fim ; i++) {

                        calculo_parcial+= matriz[i]*matriz[i];          //calculo da soma parcial
                        contador=contador+1;                            //conatra elemento somado

                }

                pthread_mutex_lock (&buffer_mutex);                     //regiao critica assegura-se que tem exlusividade para gravar os dados

                buffer[items_buffer+1]=calculo_parcial;                 //envio dos items para o buffer
                items_buffer=items_buffer+1;                            // contador de items no buffer

                //printf("o meu buffer tem %d items a soma parcial é de %d e o buffer tem %d\n",items_buffer,calculo_parcial,buffer[items_buffer]);
                //printf ("A thread %d calculou o bloco de %d a %d\n", id_threads, inicio_inicial+1, fim);

                pthread_mutex_unlock(&buffer_mutex);                    //desbloqueio do mutex para libertar o processador às outras threads
                //pthread_cond_signal(&consumir);                           // sinalizar a thread somador que existem items no buffer mais uma vez poderiamos usar o sched yield, que nao seria tao eficaz
                sched_yield();                                          //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO

                //a partir deste momento caso exitam blocos
                //por computar as threads vao agarrar um novo bloco e computalo
                //segue exatamente a mesma estrutura indicada em cima
                //mas agora nao existe obrigatoriedade de cada thread ter um bloco

        while (1) {

                pthread_mutex_lock(&indice_mutex);

                if (numero_para_comeco >= n) {
                        pthread_mutex_unlock(&indice_mutex);
                        break;
                }

                inicio = numero_para_comeco;

                if ((inicio + nbloco) < n)
                        numero_para_comeco = fim = inicio + nbloco;
                else
                        numero_para_comeco = fim = n;

                pthread_mutex_unlock(&indice_mutex);

                calculo_parcial = 0;                        // inicializaçao da soma parcial de volta a 0

                //printf ("A thread %d está a calcular o bloco de %d a %d\n", id_threads, inicio+1, fim);

                    //pthread_mutex_lock (&buffer_mutex);

                    while(items_buffer==nt){

                            //pthread_cond_wait(&produzir,&buffer_mutex);
                            //pthread_mutex_unlock(&buffer_mutex);
                            sched_yield();                              //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
                        }

                    for (i = inicio; i < fim ; i++) {

                        calculo_parcial+= matriz[i]*matriz[i];
                        contador=contador+1;                            //conatra elemento somado

                }

                pthread_mutex_lock (&buffer_mutex);

                buffer[items_buffer+1]=calculo_parcial;
                items_buffer=items_buffer+1;

                //printf("o meu buffer tem %d items a soma parcial é de %d e o buffer tem %d\n",items_buffer,calculo_parcial,buffer[items_buffer]);
                //printf ("A thread %d calculou o bloco de %d a %d\n", id_threads, inicio+1, fim);

                pthread_mutex_unlock (&buffer_mutex);
                //pthread_cond_signal(&consumir);
                sched_yield();                      //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO
        }

        sinal_saida=sinal_saida+1;                      //forma de sinalizar que a thread saiu para que a thread de soma e que limpa o buffer saiba que pode acabar

        printf("tarefa %d calculou %d elementos\n",id_threads,contador);
        //printf("tarefa %d de saída\n",id_threads);

        pthread_exit(NULL);

}

//aqui é apresentada a funcao que soma as somas parcias que estao no buffer e o limpa

void *somadora(void *ts)
{

    pthread_mutex_lock(&criacao_thread_mutex);          //bloqueamos o mutex para que seja dado o sinal de que a thread foi criada

    //printf("Sou a thread somadora\n");

    pthread_cond_signal(&cond);                         //sinalizamos a main thread que a thread foi criada

    pthread_mutex_unlock(&criacao_thread_mutex);        //desbloqueio do mutex para que as threads estejam á vontade

    pthread_mutex_lock(&buffer_mutex);                  //estramos numa operaçao critica onde os dados nao se podem perder, bloqueamos o mutex

        while(items_buffer==0){

            //emquanto o buffer tiver 0 elemnetos
            //sinalizamos as threads que podem produzir
            //é feita entao uma condicao de espera ou
            //podemos usar um sched yield

            //pthread_cond_wait(&consumir,&buffer_mutex);
            pthread_mutex_unlock(&buffer_mutex);                //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
            sched_yield();
        }

        while(sinal_saida<nt){                      //enquanto todas as thread nao se extinguirem esta condicao é valida

            while(items_buffer!=0){                 //sempre que o buffer é diferente de 0 é calculado a soma das somas parciais e o buffer é esvaziado

                soma_global+=buffer[items_buffer];  //actualizacao da soma global
                items_buffer=items_buffer-1;        //reduçao do buffer

                //printf("o meu buffer ficou com %d items\n",items_buffer);

            }

            pthread_mutex_unlock(&buffer_mutex);    //computacao realizada podemos desbloquear o mutex
            //pthread_cond_signal(&produzir);           //envio de sinal que as threads podem produzir realizar mais somas parciais
            sched_yield();                      //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO
        }

        //quando todas as thread terminaram
        //a tarefa soma terá que rodar mais uma
        //para verificar se nao sobraram elementos no buffer_mutex
        //a logica é a mesma apresentada anteriormente

        pthread_mutex_lock(&soma_final_mutex);

        while(items_buffer!=0){

                soma_global+=buffer[items_buffer];
                items_buffer=items_buffer-1;

                //printf("o meu buffer ficou com %d items\n",items_buffer);
            }

        pthread_mutex_unlock(&soma_final_mutex);

        //printf("Sou a thread somadora estou de saida\n");

        pthread_exit(NULL);

}

//funçao princial

int main(int argc, char *argv[])
{
        int i,z;                            //defeinao de variaveis

        //recolha de elementos da linha de comandos

        nt=atoi(argv[1]);
        n=atoi(argv[2]);
        nbloco=atoi(argv[3]);

        //verificacao dos elementos inceridos pelo utilizador

        if(argc!=4){
            printf("Utilização: ./mtss nt n nbloco\n");
            exit(1);}

        if(nt<1){
            printf("O numero de processos terá que ser pelo menos 1\n");
            exit(1);}

        if(n<1||n>999){
        printf("O n tem que estar comprefimido entre 1 e 999\n");
        exit(1);}

        if(nbloco<1){
        printf("O bloco tem que ser pelo menos 1\n");
        exit(1);
        }

        printf("Soma do quadrado dos %d primeiros numeros naturais com %d tarefas e blocos de %d termos\n",n,nt,nbloco);

        //defeniçao de threads e attributos

        pthread_t threads_calculadora[nt];
        pthread_t thread_soma;
        pthread_attr_t attr;

        //alocacar espaço para a estrutura que vai ser passada às threads

        estrutura_geral * estrutura = malloc(sizeof(estrutura_geral));

        //alocarçao de espaço para a matriz com os valores de calculo e para o buffer

        matriz = malloc(sizeof(int)*n);
        buffer = malloc(sizeof(int)*nt);

        // preenchimento da matriz com os valores de n

        for(z=0;z<n;z++){

            matriz[z]=z+1;

        }

        //inicializaçao dos mutex

        pthread_mutex_init(&indice_mutex, NULL);
        pthread_mutex_init(&criacao_thread_mutex,NULL);
        pthread_mutex_init(&soma_final_mutex,NULL);
        pthread_mutex_init(&buffer_mutex,NULL);

        //inicializaçao das condicoes

        pthread_cond_init(&cond,NULL);
        //pthread_cond_init(&produzir,NULL);                    //DESTIVAR EM CASO DE USO DO SCHED YIELD
        //pthread_cond_init(&consumir,NULL);                    //DESTIVAR EM CASO DE USO DO SCHED YIELD

        // inicializacao e defenicao de atributos

        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //este atributo já é predefenido mas nunca é demais garantir

        numero_para_comeco=nbloco*nt;       //defenicao da variavel que controla o numero para a thread começar quando está no loop while(1)
        estrutura->inicio_inicial=0;        //inicializaçao da variavel

        //criaçao da thread soma que usara a funcao somadora e reduzira o buffer

        pthread_create(&thread_soma, &attr, somadora,estrutura);
        pthread_cond_wait(&cond,&criacao_thread_mutex);             //espera o sinal que a thread está criada

        //criaçao das threads calculadoras

        for (i=0; i<nt; i++) {

                ++estrutura->id_threads;            //numero de ordem da thread

                pthread_create(&threads_calculadora[i], &attr, calculadoras,estrutura);     //cria a thread

                estrutura->inicio_inicial=i*nbloco; //define o inicio da thread

                pthread_cond_wait(&cond,&criacao_thread_mutex); //espera que seja sinalizada que a thread foi criada
        }

        //espera que todas a threads terminem

        for (i=0; i<nt; i++) {

                pthread_join(threads_calculadora[i], NULL);

        }

        pthread_join(thread_soma, NULL);

        resultado_esperado = (n*(n+1)*((2*n)+1))/6;

        printf("Soma Total= %d\n",soma_global);
        printf("Resultado esperado = %d\n",resultado_esperado);

        //Libertar memória

        pthread_attr_destroy(&attr);
        pthread_mutex_destroy(&indice_mutex);
        pthread_mutex_destroy(&criacao_thread_mutex);
        pthread_mutex_destroy(&soma_final_mutex);
        pthread_mutex_destroy(&buffer_mutex);
        //pthread_cond_destroy(&produzir);                      //DESTIVAR EM CASO DE USO DO SCHED YIELD
        //pthread_cond_destroy(&consumir);                      //DESTIVAR EM CASO DE USO DO SCHED YIELD

        return 0;
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
So i have these code, i want to define my number of interactions manualy, so for each thread basicaly i define lets say 10 interactios so each thread will compute a block of 10. If i do that the thread wont go after the first 10.

Basically what i want is evrytime a thread finishes computing 10 interactions goes and does another block of ten, lets say the 100 in 10 interactions have 10 blocks i want for example 4 threads working each one computes a block when finishing goes and grab another block

Can anyone help?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NTHREADS      4
#define ARRAYSIZE   1000000
#define ITERATIONS   ARRAYSIZE / NTHREADS

double  sum=0.0, a[ARRAYSIZE];
pthread_mutex_t sum_mutex;

void *do_work(void *tid)
{
  int i, start, *mytid, end;
  double mysum=0.0;

  /* Initialize my part of the global array and keep local sum */
  mytid = (int *) tid;
  start = (*mytid * ITERATIONS);
  end = start + ITERATIONS;
  printf ("Thread %d doing iterations %d to %d\n",*mytid,start,end-1);
  for (i=start; i < end ; i++) {
    a[i] = i * 1.0;
    mysum = mysum + a[i];
    }

  /* Lock the mutex and update the global sum, then exit */
  pthread_mutex_lock (&sum_mutex);
  sum = sum + mysum;
  pthread_mutex_unlock (&sum_mutex);
  pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
  int i, start, tids[NTHREADS];
  pthread_t threads[NTHREADS];
  pthread_attr_t attr;

  /* Pthreads setup: initialize mutex and explicitly create threads in a
     joinable state (for portability).  Pass each thread its loop offset */
  pthread_mutex_init(&sum_mutex, NULL);
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  for (i=0; i<NTHREADS; i++) {
    tids[i] = i;
    pthread_create(&threads[i], &attr, do_work, (void *) &tids[i]);
    }

  /* Wait for all threads to complete then print global sum */
  for (i=0; i<NTHREADS; i++) {
    pthread_join(threads[i], NULL);
  }
  printf ("Done. Sum= %e \n", sum);

  sum=0.0;
  for (i=0;i<ARRAYSIZE;i++){
  a[i] = i*1.0;
  sum = sum + a[i]; }
  printf("Check Sum= %e\n",sum);

  /* Clean up and exit */
  pthread_attr_destroy(&attr);
  pthread_mutex_destroy(&sum_mutex);
  pthread_exit (NULL);
}

I have tried inumerous aways but cant get the logic to do that. Maybe a while loop inside the void?? anay ideas?

Body:
So,here is the problem solved for the ones that are intrested.

#include <pthread.h>    //utilizado para as pthreads
#include <stdio.h>      //utilizado para os printf
#include <stdlib.h>     //utilizado para o malloc

int nt,n,nbloco;                                                                        // defenição das variáveis base pedidas
int resultado_esperado = 0, *matriz, *buffer,sinal_saida,soma_global, items_buffer=0;   //defenição das variaveis udadas para calculo e controlo do programa

pthread_mutex_t indice_mutex, criacao_thread_mutex,buffer_mutex,soma_final_mutex;       // defenição dos mutex para exclusividade, poderia ser usado um so mutex para garantir que nao exista confusoes de desbloqueio opteou-se por criacao de mutex exclusivos para as operacoes

//CASO USE O PROGRAMA COM A FUNCAO SCHED YIELD
//DESATIVAR AS CONDICOES PRODUZIR E CONSUMIR

pthread_cond_t cond/*, produzir, consumir*/;                                                // defenição de condições para sinalizar threads criadas e sinalizaao de buffer cheio (mais rapido do que usar o sched_yield as duas opcoes estao acessiveis)

static int numero_para_comeco = 0;                                                      //numero de controlo para saber que bloco a thread vai processar

typedef struct {

    //esta estrutara vai passar os valores para as threads
    //valores que vão diferir de uma thread para
    //a outra, dái se encontrarem dentro da estrutura.

  int inicio_inicial;
  int id_threads;

}estrutura_geral;

// esta primeira função representa a função das tarefas
// calculadoras está dividida em duas partes um primeira
//que processa o bloco associado de inicio conforme a sequencia de numero de ordem
//(cada thread obriagtoriamento computa um bloco)
// e uma segunda que permite qualquer thread agarrar um novo bloco
// esta funç]ao tem um apontador que direciona para a estrutura

void *calculadoras(void *es)
{
        int i, inicio, fim, contador;                                           //defenicao de variaveis
        int calculo_parcial = 0;                                    //defenicao variavel soma parcial

        pthread_mutex_lock(&criacao_thread_mutex);                  //bloqueio do mutex para garantir a leitura da estrutura e o envio de sinal da thread criada

        estrutura_geral * const estrutura = es;                     //pointer é criado para a estrutura

        int const id_threads = estrutura->id_threads;               //leitura dos elemnetos da estrutura
        int const inicio_inicial = estrutura->inicio_inicial;

        contador=0;                                                 //incializaçao do conatdor

        if ((inicio_inicial+nbloco) < n){                           //verificaçao do tamanho do bloco a calcular
            fim = inicio_inicial + nbloco;
        }else{
            fim = n;
        }

        pthread_cond_signal(&cond);                                 //sinalizacao à main thread que a thread foi criada

        pthread_mutex_unlock(&criacao_thread_mutex);                //desbloqueio do mutex para a variavel de condicao na main thread ser usada

        sched_yield();                                              //nao é necessário estar aqui mas ao fazer garanto que outras threads tenham ainda mais oportunidade.

        //printf ("A thread %d está a calcular o bloco de %d a %d\n", id_threads, inicio_inicial+1, fim);

        //primeira parte da computacao onde os valores para
        //soma passados orbriatoriamente por oredem de criacao da thread

                //pthread_mutex_lock (&buffer_mutex);                   //(quando usar as condiçoes ou fazer o calculo do bloco completo)estamos a entrar numa regiao onde a computacao vai ser feira precisamos de boquea o mutex para que nao exista perda de dados

                 while(items_buffer==nt){

                 //enquanto o buffer for igual ao numero de tarefas
                 //existem duas opçoes ou a thread manda um sinal à thread que
                 //soma os valores do buffer para limpar o buffer
                 //ou entao podemos optar por nao mandar o sinal desbloquear o mutex
                 // e simplesmente libertar a tarefa com sched_yield
                 //o sinal acaba por se mais eficaz pois nao e certo que com o sched yield
                 //a proxima tarefa seja a somadora

                            //pthread_cond_wait(&produzir,&buffer_mutex);
                            //pthread_mutex_unlock(&buffer_mutex);              //ativar quando o mutex for bloqueado anteriormente
                            sched_yield();                                      //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
                        }

                    for (i = inicio_inicial; i < fim ; i++) {

                        calculo_parcial+= matriz[i]*matriz[i];          //calculo da soma parcial
                        contador=contador+1;                            //conatra elemento somado

                }

                pthread_mutex_lock (&buffer_mutex);                     //regiao critica assegura-se que tem exlusividade para gravar os dados

                buffer[items_buffer+1]=calculo_parcial;                 //envio dos items para o buffer
                items_buffer=items_buffer+1;                            // contador de items no buffer

                //printf("o meu buffer tem %d items a soma parcial é de %d e o buffer tem %d\n",items_buffer,calculo_parcial,buffer[items_buffer]);
                //printf ("A thread %d calculou o bloco de %d a %d\n", id_threads, inicio_inicial+1, fim);

                pthread_mutex_unlock(&buffer_mutex);                    //desbloqueio do mutex para libertar o processador às outras threads
                //pthread_cond_signal(&consumir);                           // sinalizar a thread somador que existem items no buffer mais uma vez poderiamos usar o sched yield, que nao seria tao eficaz
                sched_yield();                                          //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO

                //a partir deste momento caso exitam blocos
                //por computar as threads vao agarrar um novo bloco e computalo
                //segue exatamente a mesma estrutura indicada em cima
                //mas agora nao existe obrigatoriedade de cada thread ter um bloco

        while (1) {

                pthread_mutex_lock(&indice_mutex);

                if (numero_para_comeco >= n) {
                        pthread_mutex_unlock(&indice_mutex);
                        break;
                }

                inicio = numero_para_comeco;

                if ((inicio + nbloco) < n)
                        numero_para_comeco = fim = inicio + nbloco;
                else
                        numero_para_comeco = fim = n;

                pthread_mutex_unlock(&indice_mutex);

                calculo_parcial = 0;                        // inicializaçao da soma parcial de volta a 0

                //printf ("A thread %d está a calcular o bloco de %d a %d\n", id_threads, inicio+1, fim);

                    //pthread_mutex_lock (&buffer_mutex);

                    while(items_buffer==nt){

                            //pthread_cond_wait(&produzir,&buffer_mutex);
                            //pthread_mutex_unlock(&buffer_mutex);
                            sched_yield();                              //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
                        }

                    for (i = inicio; i < fim ; i++) {

                        calculo_parcial+= matriz[i]*matriz[i];
                        contador=contador+1;                            //conatra elemento somado

                }

                pthread_mutex_lock (&buffer_mutex);

                buffer[items_buffer+1]=calculo_parcial;
                items_buffer=items_buffer+1;

                //printf("o meu buffer tem %d items a soma parcial é de %d e o buffer tem %d\n",items_buffer,calculo_parcial,buffer[items_buffer]);
                //printf ("A thread %d calculou o bloco de %d a %d\n", id_threads, inicio+1, fim);

                pthread_mutex_unlock (&buffer_mutex);
                //pthread_cond_signal(&consumir);
                sched_yield();                      //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO
        }

        sinal_saida=sinal_saida+1;                      //forma de sinalizar que a thread saiu para que a thread de soma e que limpa o buffer saiba que pode acabar

        printf("tarefa %d calculou %d elementos\n",id_threads,contador);
        //printf("tarefa %d de saída\n",id_threads);

        pthread_exit(NULL);

}

//aqui é apresentada a funcao que soma as somas parcias que estao no buffer e o limpa

void *somadora(void *ts)
{

    pthread_mutex_lock(&criacao_thread_mutex);          //bloqueamos o mutex para que seja dado o sinal de que a thread foi criada

    //printf("Sou a thread somadora\n");

    pthread_cond_signal(&cond);                         //sinalizamos a main thread que a thread foi criada

    pthread_mutex_unlock(&criacao_thread_mutex);        //desbloqueio do mutex para que as threads estejam á vontade

    pthread_mutex_lock(&buffer_mutex);                  //estramos numa operaçao critica onde os dados nao se podem perder, bloqueamos o mutex

        while(items_buffer==0){

            //emquanto o buffer tiver 0 elemnetos
            //sinalizamos as threads que podem produzir
            //é feita entao uma condicao de espera ou
            //podemos usar um sched yield

            //pthread_cond_wait(&consumir,&buffer_mutex);
            pthread_mutex_unlock(&buffer_mutex);                //PARA ACTIVAR O SCHED YIELD DESATIVE A CONDIÇAO E ATIVE O MUTEX
            sched_yield();
        }

        while(sinal_saida<nt){                      //enquanto todas as thread nao se extinguirem esta condicao é valida

            while(items_buffer!=0){                 //sempre que o buffer é diferente de 0 é calculado a soma das somas parciais e o buffer é esvaziado

                soma_global+=buffer[items_buffer];  //actualizacao da soma global
                items_buffer=items_buffer-1;        //reduçao do buffer

                //printf("o meu buffer ficou com %d items\n",items_buffer);

            }

            pthread_mutex_unlock(&buffer_mutex);    //computacao realizada podemos desbloquear o mutex
            //pthread_cond_signal(&produzir);           //envio de sinal que as threads podem produzir realizar mais somas parciais
            sched_yield();                      //PODE ATIVAR O SCHED YIED PARA ISSO DESATIVE A CONDIÇAO
        }

        //quando todas as thread terminaram
        //a tarefa soma terá que rodar mais uma
        //para verificar se nao sobraram elementos no buffer_mutex
        //a logica é a mesma apresentada anteriormente

        pthread_mutex_lock(&soma_final_mutex);

        while(items_buffer!=0){

                soma_global+=buffer[items_buffer];
                items_buffer=items_buffer-1;

                //printf("o meu buffer ficou com %d items\n",items_buffer);
            }

        pthread_mutex_unlock(&soma_final_mutex);

        //printf("Sou a thread somadora estou de saida\n");

        pthread_exit(NULL);

}

//funçao princial

int main(int argc, char *argv[])
{
        int i,z;                            //defeinao de variaveis

        //recolha de elementos da linha de comandos

        nt=atoi(argv[1]);
        n=atoi(argv[2]);
        nbloco=atoi(argv[3]);

        //verificacao dos elementos inceridos pelo utilizador

        if(argc!=4){
            printf("Utilização: ./mtss nt n nbloco\n");
            exit(1);}

        if(nt<1){
            printf("O numero de processos terá que ser pelo menos 1\n");
            exit(1);}

        if(n<1||n>999){
        printf("O n tem que estar comprefimido entre 1 e 999\n");
        exit(1);}

        if(nbloco<1){
        printf("O bloco tem que ser pelo menos 1\n");
        exit(1);
        }

        printf("Soma do quadrado dos %d primeiros numeros naturais com %d tarefas e blocos de %d termos\n",n,nt,nbloco);

        //defeniçao de threads e attributos

        pthread_t threads_calculadora[nt];
        pthread_t thread_soma;
        pthread_attr_t attr;

        //alocacar espaço para a estrutura que vai ser passada às threads

        estrutura_geral * estrutura = malloc(sizeof(estrutura_geral));

        //alocarçao de espaço para a matriz com os valores de calculo e para o buffer

        matriz = malloc(sizeof(int)*n);
        buffer = malloc(sizeof(int)*nt);

        // preenchimento da matriz com os valores de n

        for(z=0;z<n;z++){

            matriz[z]=z+1;

        }

        //inicializaçao dos mutex

        pthread_mutex_init(&indice_mutex, NULL);
        pthread_mutex_init(&criacao_thread_mutex,NULL);
        pthread_mutex_init(&soma_final_mutex,NULL);
        pthread_mutex_init(&buffer_mutex,NULL);

        //inicializaçao das condicoes

        pthread_cond_init(&cond,NULL);
        //pthread_cond_init(&produzir,NULL);                    //DESTIVAR EM CASO DE USO DO SCHED YIELD
        //pthread_cond_init(&consumir,NULL);                    //DESTIVAR EM CASO DE USO DO SCHED YIELD

        // inicializacao e defenicao de atributos

        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //este atributo já é predefenido mas nunca é demais garantir

        numero_para_comeco=nbloco*nt;       //defenicao da variavel que controla o numero para a thread começar quando está no loop while(1)
        estrutura->inicio_inicial=0;        //inicializaçao da variavel

        //criaçao da thread soma que usara a funcao somadora e reduzira o buffer

        pthread_create(&thread_soma, &attr, somadora,estrutura);
        pthread_cond_wait(&cond,&criacao_thread_mutex);             //espera o sinal que a thread está criada

        //criaçao das threads calculadoras

        for (i=0; i<nt; i++) {

                ++estrutura->id_threads;            //numero de ordem da thread

                pthread_create(&threads_calculadora[i], &attr, calculadoras,estrutura);     //cria a thread

                estrutura->inicio_inicial=i*nbloco; //define o inicio da thread

                pthread_cond_wait(&cond,&criacao_thread_mutex); //espera que seja sinalizada que a thread foi criada
        }

        //espera que todas a threads terminem

        for (i=0; i<nt; i++) {

                pthread_join(threads_calculadora[i], NULL);

        }

        pthread_join(thread_soma, NULL);

        resultado_esperado = (n*(n+1)*((2*n)+1))/6;

        printf("Soma Total= %d\n",soma_global);
        printf("Resultado esperado = %d\n",resultado_esperado);

        //Libertar memória

        pthread_attr_destroy(&attr);
        pthread_mutex_destroy(&indice_mutex);
        pthread_mutex_destroy(&criacao_thread_mutex);
        pthread_mutex_destroy(&soma_final_mutex);
        pthread_mutex_destroy(&buffer_mutex);
        //pthread_cond_destroy(&produzir);                      //DESTIVAR EM CASO DE USO DO SCHED YIELD
        //pthread_cond_destroy(&consumir);                      //DESTIVAR EM CASO DE USO DO SCHED YIELD

        return 0;
}


问:
deserialize json field into plain string with gson
I am trying to deserialize a json object into a java bean.
The main issue I am facing is that I'd like to treat the field object of the json string as a plain string, even if it contains a potentially correct json object.
The json structure is like this:

```<code>{
    "type":"user",
    "object":{
        "id":"1",
        ...}
}
</code>```

How can i tell gson to ignore the object value so that it doesn't get deserialized into an object? I'd like it only to be mapped to a plain String field in my bean so that I can dispose a proper deserialization for it, once I got the type from the type field.

答:
I don't know if your problem is solved. I ran into a similar question and here it is how I worked it out:

JsonDeserializer allows you to make you own adapter to deserialize that **:

```<code>class JavaBeanDeserializer implements JsonDeserializer<JavaBeanObject>() {
    public JavaBeanObject fromJson(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    // return JavaBeanObject built using your logic.
}
</code>```

You've to register JavaBeanDeserializer to Gson object when building it:

```<code>Gson gson = new GsonBuilder().registerTypeAdapter(JavaBeanObject.class, new JavaBeanDeserializer()).create();
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I am trying to deserialize a json object into a java bean.
The main issue I am facing is that I'd like to treat the field object of the json string as a plain string, even if it contains a potentially correct json object.
The json structure is like this:

{
    "type":"user",
    "object":{
        "id":"1",
        ...}
}

How can i tell gson to ignore the object value so that it doesn't get deserialized into an object? I'd like it only to be mapped to a plain String field in my bean so that I can dispose a proper deserialization for it, once I got the type from the type field.

Body:
I don't know if your problem is solved. I ran into a similar question and here it is how I worked it out:

JsonDeserializer allows you to make you own adapter to deserialize that **:

class JavaBeanDeserializer implements JsonDeserializer<JavaBeanObject>() {
    public JavaBeanObject fromJson(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    // return JavaBeanObject built using your logic.
}

You've to register JavaBeanDeserializer to Gson object when building it:

Gson gson = new GsonBuilder().registerTypeAdapter(JavaBeanObject.class, new JavaBeanDeserializer()).create();

ContentLicense: CC BY-SA 3.0


问:
Multiple radio buttons won't work, just the first one
I'm new at coding and I must be making a simple mistake that I can't figure out.

My angular aplications has two Modals, the first is a form to add and the second is the edit.

When I'm using the first modal the radio button works, but when I try the second the radio buttons wont work. As if they were disabled.

One thing that I've noticed is that when I use the tab button on my keyboard the radio buttons are selectable through the keyboard.

I've also noticed that if I change the code of the modal that has the radio button that was not working before the code that was working this inverts the issue.

The code that is "rendered" first works.

```<code><!-- fist RadioButton -->
<div class="md-form">
  <div class="d-flex justify-content-around">
    <p>Tipo da Instituição: </p>
    <div class="custom-control custom-radio custom-control-inline">
      <input formControlName="tipoedit" type="radio" class="custom-control-input" id="publica" name="tipoedit"
        value="Publica">
      <label class="custom-control-label" for="publica">Publica</label>
    </div>
    <div class="custom-control custom-radio custom-control-inline">
      <input formControlName="tipoedit" type="radio" class="custom-control-input" id="privado" name="tipoedit"
        value="Privado">
      <label class="custom-control-label" for="publica">Privado</label>
    </div>
  </div>
  <div *ngIf="submitted && fedit.type.errors" class="invalidFeedback">
    <div *ngIf="fedit.type.errors.required">Tipo é obrigatorio</div>
  </div>
</div>

<!-- Second RadioButton -->
<div class="md-form">
  <div class="d-flex justify-content-around">
    <p>Tipo da Instituição: </p>
    <div class="custom-control custom-radio custom-control-inline">
      <input formControlName="tipo" type="radio" class="custom-control-input" id="publica" name="tipo"
        value="Publica">
      <label class="custom-control-label" for="publica">Publica</label>
    </div>
    <div class="custom-control custom-radio custom-control-inline">
      <input formControlName="tipo" type="radio" class="custom-control-input" id="privado" name="tipo"
        value="Privado">
      <label class="custom-control-label" for="privado">Privado</label>
    </div>
  </div>
  <div *ngIf="submitted && fadd.tipo.errors" class="invalidFeedback">
    <div *ngIf="fadd.tipo.errors.required">Tipo é obrigatorio</div>
  </div>
</div>
</code>```

答:
The problem seems to be your for attributes on the  labels and the fact that you have multiple elements with the same ids. I highly recommend never having two HTML elements with similar ids.

Try changing the ids of your second radio modal (something like privadoEdit/publicaEdit )and change the for attributes accordingly.

Also, your first modal has publica in both your label's for attributes, change the second one to privado

Hope this hleps

Body:
I'm new at coding and I must be making a simple mistake that I can't figure out.

My angular aplications has two Modals, the first is a form to add and the second is the edit.

When I'm using the first modal the radio button works, but when I try the second the radio buttons wont work. As if they were disabled.

One thing that I've noticed is that when I use the tab button on my keyboard the radio buttons are selectable through the keyboard.

I've also noticed that if I change the code of the modal that has the radio button that was not working before the code that was working this inverts the issue.

The code that is "rendered" first works.

Tipo da Instituição:

      <input formControlName="tipoedit" type="radio" class="custom-control-input" id="publica" name="tipoedit"
        value="Publica">
      Publica

      <input formControlName="tipoedit" type="radio" class="custom-control-input" id="privado" name="tipoedit"
        value="Privado">
      Privado

Tipo é obrigatorio

Tipo da Instituição:

      <input formControlName="tipo" type="radio" class="custom-control-input" id="publica" name="tipo"
        value="Publica">
      Publica

      <input formControlName="tipo" type="radio" class="custom-control-input" id="privado" name="tipo"
        value="Privado">
      Privado

Tipo é obrigatorio


问:
Spring boot tests in memory db data not persisting between tests
I'm trying to do a test suite to check a @oneToMany relation i have

I have a book_category and a book
but my issue is that i have several small tests inside a test class and it seems that the db (H2) is being deleted after each test

here is my code

```<code>@Slf4j
@RunWith(SpringRunner.class)
@DataJpaTest
@TestPropertySource(locations="classpath:test.properties")
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class BookServiceTest {

    @Autowired
    private BookService bookService;

    @Autowired
    private BookCategoryService categoryService;

    @Test
    @Order(1)
    public void insertBookCategories() {
        BookCategory cat1 = new BookCategory();
        cat1.setCategoryCode(32);
        cat1.setCategoryName("Category 1");
        BookCategory cat2 = new BookCategory();
        cat2.setCategoryCode(323);
        cat2.setCategoryName("Category 2");
        categoryService.save(cat1);
        categoryService.save(cat2);
        List<BookCategory> categories = categoryService.findAll();
        assertEquals(2, categories.size());
        log.debug("Executed test number 1");
    }

    @Test
    @Order(2)
    public void createBookWithCategory() {
        Book book = new Book();
        book.setDescription("Test Book");
        book.setNumberOfSales(5);
        book.setTitle("Test title");
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertNotNull(cat); <------- this fails!!!!
        assertEquals("Category 2", cat.getCategoryName());
        book.setCategory(cat);
        bookService.save(book);
        log.debug("Executed test number 2");
    }

    @Test
    @Order(3)
    public void deleteCategoryWithBook() {
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertEquals("Category 2", cat.getCategoryName());
        categoryService.delete(cat);
        log.debug("Executed test number 3");

    }

    @Test
    @Order(4)
    public void assertBookIsNotNull() {
        Book book = bookService.findByTitle("Test title");
        assertEquals("Test Book", book.getDescription());
        assertNull(book.getCategory());
        log.debug("Executed test number 4");

    }
</code>```

I get a null pointer when the code in test number 2 (createBookWithCategory) tries to fetch the category previously inserted in test 1

I tought that adding the @Transactional annotation would help persists the data until the entire test suite ends but its not working

here are my test.properties

```<code>h2.datasource.url=jdbc:h2:mem:somedatebase;DB_CLOSE_DELAY=-1
h2.datasource.username=sa
h2.datasource.password=
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create
</code>```

答:
H2 Database will delete everything after the last connection has been closed. If you want to circumvent that behaviour you have to add

;DB_CLOSE_DELAY=-1

After your database configuration, for example:

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

I do NOT recommend this approach, tests that are dependent on other tests are BAD PRACTICE. Every test should clear the db, set up its own expectations then run tests.

You have been warned.

Body:
I'm trying to do a test suite to check a @oneToMany relation i have

I have a book_category and a book
but my issue is that i have several small tests inside a test class and it seems that the db (H2) is being deleted after each test

here is my code

@Slf4j
@RunWith(SpringRunner.class)
@DataJpaTest
@TestPropertySource(locations="classpath:test.properties")
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class BookServiceTest {

    @Autowired
    private BookService bookService;

    @Autowired
    private BookCategoryService categoryService;

    @Test
    @Order(1)
    public void insertBookCategories() {
        BookCategory cat1 = new BookCategory();
        cat1.setCategoryCode(32);
        cat1.setCategoryName("Category 1");
        BookCategory cat2 = new BookCategory();
        cat2.setCategoryCode(323);
        cat2.setCategoryName("Category 2");
        categoryService.save(cat1);
        categoryService.save(cat2);
        List<BookCategory> categories = categoryService.findAll();
        assertEquals(2, categories.size());
        log.debug("Executed test number 1");
    }

    @Test
    @Order(2)
    public void createBookWithCategory() {
        Book book = new Book();
        book.setDescription("Test Book");
        book.setNumberOfSales(5);
        book.setTitle("Test title");
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertNotNull(cat); <------- this fails!!!!
        assertEquals("Category 2", cat.getCategoryName());
        book.setCategory(cat);
        bookService.save(book);
        log.debug("Executed test number 2");
    }

    @Test
    @Order(3)
    public void deleteCategoryWithBook() {
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertEquals("Category 2", cat.getCategoryName());
        categoryService.delete(cat);
        log.debug("Executed test number 3");

    }

    @Test
    @Order(4)
    public void assertBookIsNotNull() {
        Book book = bookService.findByTitle("Test title");
        assertEquals("Test Book", book.getDescription());
        assertNull(book.getCategory());
        log.debug("Executed test number 4");

    }

I get a null pointer when the code in test number 2 (createBookWithCategory) tries to fetch the category previously inserted in test 1

I tought that adding the @Transactional annotation would help persists the data until the entire test suite ends but its not working

here are my test.properties

h2.datasource.url=jdbc:h2:mem:somedatebase;DB_CLOSE_DELAY=-1
h2.datasource.username=sa
h2.datasource.password=
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create


问:
Android Twitter integration
Hello Friends
I have to ingrate X auth to my android apps using Xauth, any body have idea about X auth code for twitter integration , if any body have twitter Xatuh demo apps , plz send me. Twitter provide  cosumer key , secreat key of Xauth for testing pupose.

Thanks in Advance

答: Have a look at Zwitscher, who does this. Users are asked for the credentials in LoginActivity::loginXauth and then the TwitterHelper::generateAccount() checks the validity against Twitter and stores the resulting token.</p>

Title: Android Twitter integration


问:
Can I somehow give this shortcode custom css even tho Advanced settings > Custom css says "Pro only"?
For a final assignment I need to make a website in wordpress. I'm making it using an existing theme and Elementor, a drag and drop website builder. I used a shortcode widget to get posts with the tag 'featured' displayed on the homepage.  However it doesn't look very pretty. The theme & page builder I'm using only offers custom css for those that pay for the pro version. Is there a way to work around this and maybe add css directly to a file somewhere?

This is the shortcode I use to display the posts with the 'featured' tag:

```<code>[display-posts tag="featured" include_date="true" date_format="F j, Y" image_size="thumbnail" include_excerpt="true" wrapper="div" posts_per_page="1"]
</code>```

答: Typically there is an Additional CSS section in the Appearance > Customize > Additional CSS section from the admin dashboard. You can put custom CSS there.</p>

Body:
For a final assignment I need to make a website in wordpress. I'm making it using an existing theme and Elementor, a drag and drop website builder. I used a shortcode widget to get posts with the tag 'featured' displayed on the homepage.  However it doesn't look very pretty. The theme & page builder I'm using only offers custom css for those that pay for the pro version. Is there a way to work around this and maybe add css directly to a file somewhere?

This is the shortcode I use to display the posts with the 'featured' tag:

[display-posts tag="featured" include_date="true" date_format="F j, Y" image_size="thumbnail" include_excerpt="true" wrapper="div" posts_per_page="1"]


问:
My program won't sort arrays that are larger than 130
So my program is supposed to take in user input (an integer between 10 and 200) and print out an array of random numbers and print out a sorted version of that array. However, this only works when I enter in 130 or less.

I don't know what else I can do. It works but only half way. Is there any way to optimize this code? I have placed lines to help show which procedure I am having problems with.

****I ran debugger and I have left a comment where the program throws an exception error.*****

```<code>TITLE Program5    (Program5.asm)

INCLUDE Irvine32.inc

; (insert constant definitions here)
    MIN_INPUT = 10
    MAX_INPUT = 200
    LO_RANDOM = 100
    HI_RANDOM = 999

.data

; (insert variable definitions here)
intro           BYTE    "Fun with Arrays! by ", 0
instruction     BYTE    "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order", 0

request         DWORD   10
ask_user        BYTE    "How many numbers should be generated? [10 ... 200]: ", 0
error           BYTE    "Invalid input", 0

title_1         BYTE    "The unsorted random numbers: ", 0
title_2         BYTE    "The sorted list: ", 0
space           BYTE    "   ", 0

mult            DWORD   0.5

temp            DWORD   0

list            DWORD   MAX_INPUT   DUP(?)

.code
main PROC

; (insert executable instructions here)
    call    randomize
    call    introduction

    push    OFFSET request ;passed by reference
    call    getData

    call    CrLf

    push    request ; passed by value
    push    OFFSET list ; passed by reference
    call    fillArray

    push    OFFSET list
    push    request
    push    OFFSET title_1
    call    displaylist

    call    CrLf

    push    OFFSET list
    push    request
    call    sortList

    call    CrLf
;
    push    OFFSET list
    push    request
    push    OFFSET title_2
    call    displaylist

    ;push   OFFSET list
    ;push   request
    ;call   displayMedian

    exit    ; exit to operating system
main ENDP

; (insert additional procedures here)
introduction PROC

    mov     edx, OFFSET intro
    call    WriteString
    call    CrLf
    mov     edx, OFFSET instruction
    call    WriteString
    call    CrLf
    ret

introduction ENDP

getData PROC
;include parameter - request (reference)

    push    ebp ;Set up stack frame
    mov     ebp, esp

    ;get an integer from user
    mov     ebx, [ebp+8]    ;get address of request into ebx

    L1:
        mov     edx, OFFSET ask_user
        call    WriteString
        call    ReadDec

        cmp     eax, MIN_INPUT
        jl      errorMessage
        cmp     eax, MAX_INPUT
        jg      errorMessage

        cmp     eax, MIN_INPUT
        jge     endThis
        cmp     eax, MAX_INPUT
        jle     endThis

    errorMessage:
        mov     edx, OFFSET error
        call    WriteString
        call    CrLf
        jmp     L1

    endThis:
        mov     [ebx], eax
        pop     ebp
        ret     4 ; remove four more bytes from the stack (after ret @)
getData ENDP

fillArray PROC
;include parameters - request (value), array (reference)
    ; MAJORITY OF THE FOLLOWING CODE WAS EXTRACTED FROM LECTURE 20 SLIDES
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+8] ; @list in edi
    mov     ecx, [ebp+12] ; value of request in ecx

    more:
        mov     eax, HI_RANDOM
        sub     eax, LO_RANDOM
        inc     eax
        call    RandomRange
        add     eax, LO_RANDOM

        mov     [edi], eax
        add     edi, 4
        loop    more

    endmore:
        pop     ebp
        ret     8
fillArray ENDP

;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
sortList PROC
;include parameters - array (reference), request (value)
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    dec     ecx ; request - 1
    mov     ebx, 0 ; "k"

    ;for(k=0; k<request-1; k++) {
       ;i = k;
       ;for(j=k+1; j<request; j++) {
          ;if(array[j] > array[i])
             ;i = j;
       ;}
       ;exchange(array[k], array[i]);
    ;}

    firstLoop:
        mov     eax, ebx ; "i = k"

        mov     edx, ebx ; "j = k"
        inc     edx ; "j = k + 1"
        push    ecx ; pushed the first loop's counter
        mov     ecx, [ebp+8] ; made the second loop's counter = request

        secondLoop:
            mov     esi, [edi + (edx * 4)] ; array[j] ; EXCEPTION WAS THROWN HERE
            cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
            jg      greater
            jle     lesser

            greater:
                mov     eax, edx
                inc     edx
                loop    secondLoop

            lesser:
                inc     edx
                loop    secondLoop

        push    edx
        push    esi
        push    [edi + (ebx * 4)] ; array[k]
        push    [edi + (eax * 4)] ; array[i]
        call    exchangeElements
        pop     [edi + (eax * 4)]
        pop     [edi + (ebx * 4)]
        pop     esi
        pop     edx
        pop     ecx ; set the
        inc     ebx ; increment k in the first loop
        loop    firstLoop

    pop     ebp
    ret     8

sortList ENDP

exchangeElements PROC
    push    ebp
    mov     ebp, esp
    mov     esi, [ebp+12] ; array[k]
    mov     edx, [ebp+8] ; array[i]
    mov     [ebp+8], esi
    mov     [ebp+12], edx
    pop     ebp
    ret
exchangeElements ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

displayMedian PROC
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    mov     eax, ecx
    mov     ebx, 2
    cdq
    div     ebx
    cmp     edx, 0
    je      isEven
    cmp     edx, 1
    je      isOdd

            ;def nlogn_median(l):
    ;l = sorted(l)
    ;if len(l) % 2 == 1:
        ;return l[len(l) / 2]
    ;else:
        ;return 0.5 * (l[len(l) / 2 - 1] + l[len(l) / 2])

    isEven:
        mov     esi, [edi + (eax - 1)]
        add     esi, [edi + (eax)]
        mov     eax, esi
        mov     ebx, 2
        cdq
        div     ebx
        call    WriteDec

    isOdd:
        mov     eax, [edi + (eax*4)]
        call    WriteDec

    pop ebp
    ret
displayMedian ENDP

displayList PROC
    push    ebp
    mov     ebp, esp ; [ebp+4]
    mov     ecx, [ebp+12] ; @request
    mov     edi, [ebp+16] ; @list
    mov     esi, 10

    mov     edx, [ebp+8] ; @title
    call    WriteString
    call    CrLf

    show:
        mov     eax, [edi]
        call    WriteDec
        mov     edx, OFFSET space
        call    WriteString
        add     edi, 4

        dec     esi
        cmp     esi, 0
        je      callClear

    loopAgain:
        loop    show

    jmp     endshow

    callClear:
        mov     esi, 10
        call    CrLf
        jmp     loopAgain

    endshow:
        pop     ebp
        ret     12

displayList ENDP

END main
</code>```

UPDATE

答:
If you look at your registers, you'll see that edx is 0fA4h, which is larger than it should be at the line it crashes on.  ecx is a negative number.  This is a clue that your loop is executing after it should have stopped.

The problem is that the greater branch will fall thru to the lesser branch.  This will decrement ecx again, causing it to go negative and your loop will just keep running until you get the access violation.

The quick fix is to put an unconditional jmp after the loop instruction under the greater label.

A better fix is to combine the tails of the loops into a simpler conditional:

```<code>    cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
    jle     lesser
    mov     eax, edx
lesser:
    inc     edx
    loop    secondLoop
</code>```

Body:
So my program is supposed to take in user input (an integer between 10 and 200) and print out an array of random numbers and print out a sorted version of that array. However, this only works when I enter in 130 or less.

I don't know what else I can do. It works but only half way. Is there any way to optimize this code? I have placed lines to help show which procedure I am having problems with.

****I ran debugger and I have left a comment where the program throws an exception error.*****

TITLE Program5    (Program5.asm)

INCLUDE Irvine32.inc

; (insert constant definitions here)
    MIN_INPUT = 10
    MAX_INPUT = 200
    LO_RANDOM = 100
    HI_RANDOM = 999

.data

; (insert variable definitions here)
intro           BYTE    "Fun with Arrays! by ", 0
instruction     BYTE    "This program generates random numbers in the range [100 .. 999], displays the original list, sorts the list, and calculates the median value. Finally, it displays the list sorted in descending order", 0

request         DWORD   10
ask_user        BYTE    "How many numbers should be generated? [10 ... 200]: ", 0
error           BYTE    "Invalid input", 0

title_1         BYTE    "The unsorted random numbers: ", 0
title_2         BYTE    "The sorted list: ", 0
space           BYTE    "   ", 0

mult            DWORD   0.5

temp            DWORD   0

list            DWORD   MAX_INPUT   DUP(?)

.code
main PROC

; (insert executable instructions here)
    call    randomize
    call    introduction

    push    OFFSET request ;passed by reference
    call    getData

    call    CrLf

    push    request ; passed by value
    push    OFFSET list ; passed by reference
    call    fillArray

    push    OFFSET list
    push    request
    push    OFFSET title_1
    call    displaylist

    call    CrLf

    push    OFFSET list
    push    request
    call    sortList

    call    CrLf
;
    push    OFFSET list
    push    request
    push    OFFSET title_2
    call    displaylist

    ;push   OFFSET list
    ;push   request
    ;call   displayMedian

    exit    ; exit to operating system
main ENDP

; (insert additional procedures here)
introduction PROC

    mov     edx, OFFSET intro
    call    WriteString
    call    CrLf
    mov     edx, OFFSET instruction
    call    WriteString
    call    CrLf
    ret

introduction ENDP

getData PROC
;include parameter - request (reference)

    push    ebp ;Set up stack frame
    mov     ebp, esp

    ;get an integer from user
    mov     ebx, [ebp+8]    ;get address of request into ebx

    L1:
        mov     edx, OFFSET ask_user
        call    WriteString
        call    ReadDec

        cmp     eax, MIN_INPUT
        jl      errorMessage
        cmp     eax, MAX_INPUT
        jg      errorMessage

        cmp     eax, MIN_INPUT
        jge     endThis
        cmp     eax, MAX_INPUT
        jle     endThis

    errorMessage:
        mov     edx, OFFSET error
        call    WriteString
        call    CrLf
        jmp     L1

    endThis:
        mov     [ebx], eax
        pop     ebp
        ret     4 ; remove four more bytes from the stack (after ret @)
getData ENDP

fillArray PROC
;include parameters - request (value), array (reference)
    ; MAJORITY OF THE FOLLOWING CODE WAS EXTRACTED FROM LECTURE 20 SLIDES
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+8] ; @list in edi
    mov     ecx, [ebp+12] ; value of request in ecx

    more:
        mov     eax, HI_RANDOM
        sub     eax, LO_RANDOM
        inc     eax
        call    RandomRange
        add     eax, LO_RANDOM

        mov     [edi], eax
        add     edi, 4
        loop    more

    endmore:
        pop     ebp
        ret     8
fillArray ENDP

;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
sortList PROC
;include parameters - array (reference), request (value)
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    dec     ecx ; request - 1
    mov     ebx, 0 ; "k"

    ;for(k=0; k<request-1; k++) {
       ;i = k;
       ;for(j=k+1; j<request; j++) {
          ;if(array[j] > array[i])
             ;i = j;
       ;}
       ;exchange(array[k], array[i]);
    ;}

    firstLoop:
        mov     eax, ebx ; "i = k"

        mov     edx, ebx ; "j = k"
        inc     edx ; "j = k + 1"
        push    ecx ; pushed the first loop's counter
        mov     ecx, [ebp+8] ; made the second loop's counter = request

        secondLoop:
            mov     esi, [edi + (edx * 4)] ; array[j] ; EXCEPTION WAS THROWN HERE
            cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
            jg      greater
            jle     lesser

            greater:
                mov     eax, edx
                inc     edx
                loop    secondLoop

            lesser:
                inc     edx
                loop    secondLoop

        push    edx
        push    esi
        push    [edi + (ebx * 4)] ; array[k]
        push    [edi + (eax * 4)] ; array[i]
        call    exchangeElements
        pop     [edi + (eax * 4)]
        pop     [edi + (ebx * 4)]
        pop     esi
        pop     edx
        pop     ecx ; set the
        inc     ebx ; increment k in the first loop
        loop    firstLoop

    pop     ebp
    ret     8

sortList ENDP

exchangeElements PROC
    push    ebp
    mov     ebp, esp
    mov     esi, [ebp+12] ; array[k]
    mov     edx, [ebp+8] ; array[i]
    mov     [ebp+8], esi
    mov     [ebp+12], edx
    pop     ebp
    ret
exchangeElements ENDP
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------

displayMedian PROC
    push    ebp
    mov     ebp, esp ;[ebp+4]
    mov     edi, [ebp+12] ; @list in edi
    mov     ecx, [ebp+8] ; value of request in ecx

    mov     eax, ecx
    mov     ebx, 2
    cdq
    div     ebx
    cmp     edx, 0
    je      isEven
    cmp     edx, 1
    je      isOdd

            ;def nlogn_median(l):
    ;l = sorted(l)
    ;if len(l) % 2 == 1:
        ;return l[len(l) / 2]
    ;else:
        ;return 0.5 * (l[len(l) / 2 - 1] + l[len(l) / 2])

    isEven:
        mov     esi, [edi + (eax - 1)]
        add     esi, [edi + (eax)]
        mov     eax, esi
        mov     ebx, 2
        cdq
        div     ebx
        call    WriteDec

    isOdd:
        mov     eax, [edi + (eax*4)]
        call    WriteDec

    pop ebp
    ret
displayMedian ENDP

displayList PROC
    push    ebp
    mov     ebp, esp ; [ebp+4]
    mov     ecx, [ebp+12] ; @request
    mov     edi, [ebp+16] ; @list
    mov     esi, 10

    mov     edx, [ebp+8] ; @title
    call    WriteString
    call    CrLf

    show:
        mov     eax, [edi]
        call    WriteDec
        mov     edx, OFFSET space
        call    WriteString
        add     edi, 4

        dec     esi
        cmp     esi, 0
        je      callClear

    loopAgain:
        loop    show

    jmp     endshow

    callClear:
        mov     esi, 10
        call    CrLf
        jmp     loopAgain

    endshow:
        pop     ebp
        ret     12

displayList ENDP

END main

UPDATE

Body:
If you look at your registers, you'll see that edx is 0fA4h, which is larger than it should be at the line it crashes on.  ecx is a negative number.  This is a clue that your loop is executing after it should have stopped.

The problem is that the greater branch will fall thru to the lesser branch.  This will decrement ecx again, causing it to go negative and your loop will just keep running until you get the access violation.

The quick fix is to put an unconditional jmp after the loop instruction under the greater label.

A better fix is to combine the tails of the loops into a simpler conditional:

    cmp     esi, [edi + (eax * 4)] ; compare array[j] and array[i]
    jle     lesser
    mov     eax, edx
lesser:
    inc     edx
    loop    secondLoop


问:
Prepared statement return errors number 0
Problem: I'm setting up my login system which should allow the user to use either username or password to login. However my prepare statement returns Prepare failed: (0) into the console (0 is the mysql error number).

What I've tried: I have tried looking in the MySQL manual to see what Error Number 0 is but couldn't find anything.

<?php
include "../includes/config.php";
if($_SERVER["REQUEST_METHOD"] == "POST") {
        // Can be either the email or username
    $login = $_POST['login'];
    $password = $_POST['password'];

    if ( $login != "" && $password != "" ) {
        // Prepare the statement
        $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
        // Check Prepare
        if ( !$pullLogin->prepare() ) { echo ""; }
        // Bind the parameters to the statement
        $pullLogin->bind_param( "ss", $login, $login );
        // Execute it :-)
        $pullLogin->execute();
        // Store the results, I don't really knwo why but whatever
        $pullLogin->store_result();
        // Bind the password to a variable :-)
        $pullLogin->bind_result($correctPassword);
        // Free the results
        $pullLogin->free_results();
        // Close the statement
        $pullLogin->close();

        // This is hashed and I'm only echoing it to see if ^ works
        echo $correctPassword;

    }
}
?>
```

Expected:  the user can use either their username or email to login.

Actual Results: the prepare statement does not seem to work :/

答:
You are double calling prepare().

You are executing an empty statement in the if-condition when calling prepare() with no argument... so there is nothing to do and also no error (error number 0) but the result from that call is false. just check the result of the first prepare-call.

Change the second prepare-call:

```<code>if ( $login != "" && $password != "" ) {
  // Prepare the statement
  $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
  // Check Prepare
  if ( !$pullLogin->prepare() ) { echo "<script>console.log('Prepare failed: ($pullLogin->errno) $pullLogin->error');</script>"; }
</code>```

Tho the following, so you are only testing the result of the first prepare():

```<code>if ( $login != "" && $password != "" ) {
  // Prepare the statement
  $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
  // Check Prepare
  if ( !$pullLogin ) { echo "<script>console.log('Prepare failed: ($link->errno) $link->error');</script>"; }
</code>```

Body:
Problem: I'm setting up my login system which should allow the user to use either username or password to login. However my prepare statement returns Prepare failed: (0) into the console (0 is the mysql error number).

What I've tried: I have tried looking in the MySQL manual to see what Error Number 0 is but couldn't find anything.

<?php
include "../includes/config.php";
if($_SERVER["REQUEST_METHOD"] == "POST") {
        // Can be either the email or username
    $login = $_POST['login'];
    $password = $_POST['password'];

    if ( $login != "" && $password != "" ) {
        // Prepare the statement
        $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
        // Check Prepare
        if ( !$pullLogin->prepare() ) { echo ""; }
        // Bind the parameters to the statement
        $pullLogin->bind_param( "ss", $login, $login );
        // Execute it :-)
        $pullLogin->execute();
        // Store the results, I don't really knwo why but whatever
        $pullLogin->store_result();
        // Bind the password to a variable :-)
        $pullLogin->bind_result($correctPassword);
        // Free the results
        $pullLogin->free_results();
        // Close the statement
        $pullLogin->close();

        // This is hashed and I'm only echoing it to see if ^ works
        echo $correctPassword;

    }
}
?>

Expected:  the user can use either their username or email to login.

Actual Results: the prepare statement does not seem to work :/

Body:
You are double calling prepare().

You are executing an empty statement in the if-condition when calling prepare() with no argument... so there is nothing to do and also no error (error number 0) but the result from that call is false. just check the result of the first prepare-call.

Change the second prepare-call:

if ( $login != "" && $password != "" ) {
  // Prepare the statement
  $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
  // Check Prepare
  if ( !$pullLogin->prepare() ) { echo "<script>console.log('Prepare failed: ($pullLogin->errno) $pullLogin->error');</script>"; }

Tho the following, so you are only testing the result of the first prepare():

if ( $login != "" && $password != "" ) {
  // Prepare the statement
  $pullLogin = $link->prepare("SELECT hashed_password FROM users WHERE (username = '?' OR email='?')");
  // Check Prepare
  if ( !$pullLogin ) { echo "<script>console.log('Prepare failed: ($link->errno) $link->error');</script>"; }


问:
Why does this serial/modem code mess up my terminal display?
I have written some code to find any modems on a unix system using the regex /dev/tty* basically and then for any matches see if can open the port and if so send an AT command and check if the response message contains the characters 'OK'.

The code does find a modem but unfortunately it messes up the terminal display.  See below.  I notice that it also prints the AT command - see output below.  Why is my terminal display altered and how can I fix that?

After running the program, if you enter a command and enter, eg ls, the command is not shown but when  you press enter you do see the output.

Here is the code:

```<code>#include <iostream>
#include <string>
#include <unordered_map>
#include <iomanip>

#include <memory>

#include <sstream>
#include <thread>

#include <iostream>
#include <filesystem>
#include <regex>

#include <unistd.h>  // close
#include <fcntl.h>   // open, O_RDWR, etc
#include <termios.h>

#include <string.h>

#include <sys/select.h>  // timeouts for read

#include <sys/timeb.h>   // measure time taken

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        // Error from tcgetattr - can use strerror(errno)
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* fetch bytes as they become available */
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
      // Error from tcsetattr- use strerror(errno)
        return -1;
    }
    return 0;
}

long enumerate_ports(std::unordered_map <std::string, std::string>& ports) {

    // ls /dev | grep ^tty.*
    const std::regex my_filter( "^tty.*" );
    std::string path = "/dev/";
    for (const auto & entry : std::filesystem::directory_iterator(path)) {
     std::smatch sm;

     std::string tmp = entry.path().filename().string();
     // if we have a regex match attempt to open port and send AT command
     if (std::regex_match(tmp, sm, my_filter)) {
     std::string portname = entry.path().string();
         int fd = ::open(portname.c_str(), O_RDWR | O_NOCTTY);
         if (fd < 0) {
       // Error opening port
             continue;
         } else {
       // port was opened successfully
           // try to write AT command and do we get an OK response
           // baudrate 9600, 8 bits, no parity, 1 stop bit
           if(set_interface_attribs(fd, B9600) != 0) {
             ::close(fd);
         continue;
           }

           int wlen = ::write(fd, "AT\r\n", 4);
           if (wlen != 4) {
         // Error from write
               ::close(fd);
               continue;
           }

          // tcdrain() waits until all output written to the object referred
          // to by fd has been transmitted.
           tcdrain(fd);

           fd_set set;
           struct timeval timeout;

           FD_ZERO(&set); /* clear the set */
           FD_SET(fd, &set); /* add our file descriptor to the set */

           timeout.tv_sec = 0;
           timeout.tv_usec = 100000; // 100 milliseconds

           // wait for data to be read or timeout
           int rv = select(fd + 1, &set, NULL, NULL, &timeout);
           if(rv > 0) {  // no timeout or error
               unsigned char buf[80];
               const int bytes_read = ::read(fd, buf, sizeof(buf) - 1);
               if (bytes_read > 0) {
                   buf[bytes_read] = 0;
                   unsigned char* p = buf;
                   // scan for "OK"
                   for (int i = 0; i < bytes_read; ++i) {
             if (*p == 'O' && i < bytes_read - 1 && *(p+1) == 'K') {
                       // we have a positive response from device so add to ports
                       ports[portname] = "";
                       break;
                     }
                     p++;
                   }
               }
        }
       ::close(fd);
         }
     }
   }

   return ports.size();
}

int main() {

    struct timeb start, end;
    int diff;
    ftime(&start);

    // get list of ports available on system
    std::unordered_map <std::string, std::string> ports;
    long result = enumerate_ports(ports);
    std::cout << "No. found modems: " << result << std::endl;
    for (const auto& item : ports) {
        std::cout << item.first << "->" << item.second << std::endl;
    }

    ftime(&end);
    diff = (int) (1000.0 * (end.time - start.time)
        + (end.millitm - start.millitm));

    printf("Operation took %u milliseconds\n", diff);
}
</code>```

And the output:

```<code>acomber@mail:~/Documents/projects/modem/serial/gdbplay$ ls
main.cpp  main.o  Makefile  serial
acomber@mail:~/Documents/projects/modem/serial/gdbplay$ make serial
g++ -Wall -Werror -ggdb3 -std=c++17 -pedantic  -c main.cpp
g++ -o serial -Wall -Werror -ggdb3 -std=c++17 -pedantic  main.o -L/usr/lib -lstdc++fs
acomber@mail:~/Documents/projects/modem/serial/gdbplay$ sudo ./serial
[sudo] password for acomber:
AT
No. found modems: 1
                   /dev/ttyACM0->
                                 Operation took 8643 milliseconds
                                                                 acomber@mail:~/Documents/projects/modem/serial/gdbplay$
</code>```

答:
Why does this serial/modem code mess up my terminal display?

A precise answer requires you to post the terminal's settings prior to executing your code, i.e. stty -a.

The code does find a modem but unfortunately it messes up the terminal display.

The simplest (i.e. straightforward) workaround/solution is to adhere to the old (but rarely followed) advice of saving and then restoring the terminal's termios settings, as in this example.

The simple changes needed in your code would be something like (please overlook mixing of C and C++; I only know C) the following patch.

```<code> struct termios savetty;

 int set_interface_attribs(int fd, int speed)
 {
+    struct termios tty;

     if (tcgetattr(fd, &tty) < 0) {
         // Error from tcgetattr - can use strerror(errno)
         return -1;
     }
+    savetty = tty;    /* preserve original settings for restoration */

     cfsetospeed(&tty, (speed_t)speed);
     cfsetispeed(&tty, (speed_t)speed);
</code>```

Then in enumerate_ports(), the last two instances of ::close(fd); need to be replaced with the sequence that will perform the restoration:

```<code>+    if (tcsetattr(fd, &savetty) < 0) {
+        // report cannot restore attributes
+    }
     ::close(fd);
</code>```

After running the program, if you enter a command and enter, eg ls, the command is not shown ...

That is obviously the result of leaving the ECHO attribute cleared.

The "missing" carriage returns are probably due to a cleared OPOST.

Other salient attributes that were cleared by your program but probably are expected to be set by the shell are ICANON, ICRNL, and IEXTEN.

But rather than try to determine what exactly needs to be undone, the proper and guaranteed fix is to simply restore the termios settings back to its original state.

An alternative (lazy) approach would to use the stty sane command after you execute your program.

Body:
I have written some code to find any modems on a unix system using the regex /dev/tty* basically and then for any matches see if can open the port and if so send an AT command and check if the response message contains the characters 'OK'.

The code does find a modem but unfortunately it messes up the terminal display.  See below.  I notice that it also prints the AT command - see output below.  Why is my terminal display altered and how can I fix that?

After running the program, if you enter a command and enter, eg ls, the command is not shown but when  you press enter you do see the output.

Here is the code:

#include <iostream>
#include <string>
#include <unordered_map>
#include <iomanip>

#include <memory>

#include <sstream>
#include <thread>

#include <iostream>
#include <filesystem>
#include <regex>

#include <unistd.h>  // close
#include <fcntl.h>   // open, O_RDWR, etc
#include <termios.h>

#include <string.h>

#include <sys/select.h>  // timeouts for read

#include <sys/timeb.h>   // measure time taken

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        // Error from tcgetattr - can use strerror(errno)
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* fetch bytes as they become available */
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
      // Error from tcsetattr- use strerror(errno)
        return -1;
    }
    return 0;
}

long enumerate_ports(std::unordered_map <std::string, std::string>& ports) {

    // ls /dev | grep ^tty.*
    const std::regex my_filter( "^tty.*" );
    std::string path = "/dev/";
    for (const auto & entry : std::filesystem::directory_iterator(path)) {
     std::smatch sm;

     std::string tmp = entry.path().filename().string();
     // if we have a regex match attempt to open port and send AT command
     if (std::regex_match(tmp, sm, my_filter)) {
     std::string portname = entry.path().string();
         int fd = ::open(portname.c_str(), O_RDWR | O_NOCTTY);
         if (fd < 0) {
       // Error opening port
             continue;
         } else {
       // port was opened successfully
           // try to write AT command and do we get an OK response
           // baudrate 9600, 8 bits, no parity, 1 stop bit
           if(set_interface_attribs(fd, B9600) != 0) {
             ::close(fd);
         continue;
           }

           int wlen = ::write(fd, "AT\r\n", 4);
           if (wlen != 4) {
         // Error from write
               ::close(fd);
               continue;
           }

          // tcdrain() waits until all output written to the object referred
          // to by fd has been transmitted.
           tcdrain(fd);

           fd_set set;
           struct timeval timeout;

           FD_ZERO(&set); /* clear the set */
           FD_SET(fd, &set); /* add our file descriptor to the set */

           timeout.tv_sec = 0;
           timeout.tv_usec = 100000; // 100 milliseconds

           // wait for data to be read or timeout
           int rv = select(fd + 1, &set, NULL, NULL, &timeout);
           if(rv > 0) {  // no timeout or error
               unsigned char buf[80];
               const int bytes_read = ::read(fd, buf, sizeof(buf) - 1);
               if (bytes_read > 0) {
                   buf[bytes_read] = 0;
                   unsigned char* p = buf;
                   // scan for "OK"
                   for (int i = 0; i < bytes_read; ++i) {
             if (*p == 'O' && i < bytes_read - 1 && *(p+1) == 'K') {
                       // we have a positive response from device so add to ports
                       ports[portname] = "";
                       break;
                     }
                     p++;
                   }
               }
        }
       ::close(fd);
         }
     }
   }

   return ports.size();
}

int main() {

    struct timeb start, end;
    int diff;
    ftime(&start);

    // get list of ports available on system
    std::unordered_map <std::string, std::string> ports;
    long result = enumerate_ports(ports);
    std::cout << "No. found modems: " << result << std::endl;
    for (const auto& item : ports) {
        std::cout << item.first << "->" << item.second << std::endl;
    }

    ftime(&end);
    diff = (int) (1000.0 * (end.time - start.time)
        + (end.millitm - start.millitm));

    printf("Operation took %u milliseconds\n", diff);
}

And the output:

acomber@mail:~/Documents/projects/modem/serial/gdbplay$ ls
main.cpp  main.o  Makefile  serial
acomber@mail:~/Documents/projects/modem/serial/gdbplay$ make serial
g++ -Wall -Werror -ggdb3 -std=c++17 -pedantic  -c main.cpp
g++ -o serial -Wall -Werror -ggdb3 -std=c++17 -pedantic  main.o -L/usr/lib -lstdc++fs
acomber@mail:~/Documents/projects/modem/serial/gdbplay$ sudo ./serial
[sudo] password for acomber:
AT
No. found modems: 1
                   /dev/ttyACM0->
                                 Operation took 8643 milliseconds
                                                                 acomber@mail:~/Documents/projects/modem/serial/gdbplay$

Body:
Why does this serial/modem code mess up my terminal display?

A precise answer requires you to post the terminal's settings prior to executing your code, i.e. stty -a.

The code does find a modem but unfortunately it messes up the terminal display.

The simplest (i.e. straightforward) workaround/solution is to adhere to the old (but rarely followed) advice of saving and then restoring the terminal's termios settings, as in this example.

The simple changes needed in your code would be something like (please overlook mixing of C and C++; I only know C) the following patch.

 struct termios savetty;

 int set_interface_attribs(int fd, int speed)
 {
+    struct termios tty;

     if (tcgetattr(fd, &tty) < 0) {
         // Error from tcgetattr - can use strerror(errno)
         return -1;
     }
+    savetty = tty;    /* preserve original settings for restoration */

     cfsetospeed(&tty, (speed_t)speed);
     cfsetispeed(&tty, (speed_t)speed);

Then in enumerate_ports(), the last two instances of ::close(fd); need to be replaced with the sequence that will perform the restoration:

+    if (tcsetattr(fd, &savetty) < 0) {
+        // report cannot restore attributes
+    }
     ::close(fd);

After running the program, if you enter a command and enter, eg ls, the command is not shown ...

That is obviously the result of leaving the ECHO attribute cleared.

The "missing" carriage returns are probably due to a cleared OPOST.

Other salient attributes that were cleared by your program but probably are expected to be set by the shell are ICANON, ICRNL, and IEXTEN.

But rather than try to determine what exactly needs to be undone, the proper and guaranteed fix is to simply restore the termios settings back to its original state.

An alternative (lazy) approach would to use the stty sane command after you execute your program.


问:
how can I use ReactNative WebView component to show a specific part of a webpage in my Android app?
I want to use ReactNative webView component in my android app and show just a specific part of a web-page. for example I want to show the contents specified by the red rectangle in the image below:

and I don't need the other parts of the webpage.
I can show the whole page by the code below:

```<code><WebView
  source={{ uri: https://github.com/TrySound }}
  style={{ marginTop: 20 }}
/>
</code>```

but don't know how to show just the contents in the red rectangle. Can anyone help me with this issue please?

答:
WebView isn't going to work in your situation. Github does have a RESTful API. You can make a GET request for a username. You'll recieve a JSON object and the information you want will be under bio.

https://developer.github.com/v3/users/#get-a-single-user

You can use the fetch api to get your bio

```<code>function getBio(){
  return fetch('https://api.github.com/users/trysound')
  .then(function(response) { return response.json();})
  .then(function(data) {return data.bio;});
}
</code>```

and to access the result of the api request you can do the following

```<code>getBio().then(function(bio){
    // insert your code here to handle the string for your bio on github
    console.log(bio);
});
</code>```

Body:
I want to use ReactNative webView component in my android app and show just a specific part of a web-page. for example I want to show the contents specified by the red rectangle in the image below:

and I don't need the other parts of the webpage.
I can show the whole page by the code below:

<WebView
  source={{ uri: https://github.com/TrySound }}
  style={{ marginTop: 20 }}
/>

but don't know how to show just the contents in the red rectangle. Can anyone help me with this issue please?

Body:
WebView isn't going to work in your situation. Github does have a RESTful API. You can make a GET request for a username. You'll recieve a JSON object and the information you want will be under bio.

https://developer.github.com/v3/users/#get-a-single-user

You can use the fetch api to get your bio

function getBio(){
  return fetch('https://api.github.com/users/trysound')
  .then(function(response) { return response.json();})
  .then(function(data) {return data.bio;});
}

and to access the result of the api request you can do the following

getBio().then(function(bio){
    // insert your code here to handle the string for your bio on github
    console.log(bio);
});


问:
Decoding ASN.1 to String and Passing to Get-DateTime
Using PowerShell, I'm trying to convert ASN.1 from a Certificate Revocation List's Next Publish extension to a Date-Time object using System.Security.Cryptography.AsnEncodedData to extract the date/time as a string; which I then planned to pass to Get-DateTime.  The object has a Format method which returns the decoded value as a string (according to the documentation).

In the snippet below the Base-64 ASN.1 value is taken from a real CRL.

```<code>$textDateTime = "31 May 2019 07:04:50"

$asnBase64 = "Fw0xOTA1MzEwNjA0NTBa"

# 1.3.6.1.4.1.311.21.4 is the OID for Next Update extension
$extAsnDecoded = New-Object System.Security.Cryptography.AsnEncodedData(
                    '1.3.6.1.4.1.311.21.4',
                    [System.Convert]::FromBase64String($asnBase64))

$nextUpdateString = $extAsnDecoded.format($false) # false for single line result

$textDateTime
$nextUpdateString

Get-Date $textDateTime
Get-Date $nextUpdateString
</code>```

The above returns:

```<code>31 May 2019 07:04:50
31 May 2019 07:04:50

31 May 2019 07:04:50
Cannot bind parameter 'Date'. Cannot convert value "31 May 2019 07:04:50" to type "System.DateTime". Error: "String was not recognized as a va
lid DateTime."
At line:14 char:10
+ Get-Date $nextUpdateString
+          ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand
</code>```

As you can see, the two variables look identical on screen. However, while the simple string variable converts to a DateTime with Get-DateTime the value (apparently a string) decoded from ASN.1 fails.  Using the .GetType() method on each shows they are both strings.

If I look at the contents of both as ASCII, I get strange results:

```<code>$enc = [system.Text.Encoding]::ASCII

$enc.GetBytes($textDateTime) -join ","
($enc.GetBytes($textDateTime) | foreach {[char]$_}) -join ""

$enc.GetBytes($nextUpdateString) -join ","
($enc.GetBytes($nextUpdateString) | foreach {[char]$_}) -join ""
</code>```

I get:

```<code>51,49,32,77,97,121,32,50,48,49,57,32,48,55,58,48,52,58,53,48
31 May 2019 07:04:50
63,51,49,32,63,77,97,121,32,63,50,48,49,57,32,48,55,58,48,52,58,53,48
?31 ?May ?2019 07:04:50
</code>```

As you can see, there are extra question marks (ASCII character 63) in the version returned by decoding the ASN.1; which may explain why Get-DateTime fails.

What's going on here?  More importantly, how can I get the string decoded from the ASN.1 to be a valid input to Get-DateTime?

答:
The string returned by AsnEncodedData.Format() includes a bunch of Left-to-Right formatting characters. You can replace this with a simple regex:

```<code>$nextUpdateString = $extAsnDecoded.Format($false) -replace '\p{Cf}'
</code>```

Cf is regex short-hand for the "Other, Format" unicode category, which will match (and remove) the formatting characters, after which you should be able to pass the string to Get-Date

Body:
Using PowerShell, I'm trying to convert ASN.1 from a Certificate Revocation List's Next Publish extension to a Date-Time object using System.Security.Cryptography.AsnEncodedData to extract the date/time as a string; which I then planned to pass to Get-DateTime.  The object has a Format method which returns the decoded value as a string (according to the documentation).

In the snippet below the Base-64 ASN.1 value is taken from a real CRL.

$textDateTime = "31 May 2019 07:04:50"

$asnBase64 = "Fw0xOTA1MzEwNjA0NTBa"

# 1.3.6.1.4.1.311.21.4 is the OID for Next Update extension
$extAsnDecoded = New-Object System.Security.Cryptography.AsnEncodedData(
                    '1.3.6.1.4.1.311.21.4',
                    [System.Convert]::FromBase64String($asnBase64))

$nextUpdateString = $extAsnDecoded.format($false) # false for single line result

$textDateTime
$nextUpdateString

Get-Date $textDateTime
Get-Date $nextUpdateString

The above returns:

31 May 2019 07:04:50
31 May 2019 07:04:50

31 May 2019 07:04:50
Cannot bind parameter 'Date'. Cannot convert value "31 May 2019 07:04:50" to type "System.DateTime". Error: "String was not recognized as a va
lid DateTime."
At line:14 char:10
+ Get-Date $nextUpdateString
+          ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

As you can see, the two variables look identical on screen. However, while the simple string variable converts to a DateTime with Get-DateTime the value (apparently a string) decoded from ASN.1 fails.  Using the .GetType() method on each shows they are both strings.

If I look at the contents of both as ASCII, I get strange results:

$enc = [system.Text.Encoding]::ASCII

$enc.GetBytes($textDateTime) -join ","
($enc.GetBytes($textDateTime) | foreach {[char]$_}) -join ""

$enc.GetBytes($nextUpdateString) -join ","
($enc.GetBytes($nextUpdateString) | foreach {[char]$_}) -join ""

I get:

51,49,32,77,97,121,32,50,48,49,57,32,48,55,58,48,52,58,53,48
31 May 2019 07:04:50
63,51,49,32,63,77,97,121,32,63,50,48,49,57,32,48,55,58,48,52,58,53,48
?31 ?May ?2019 07:04:50

As you can see, there are extra question marks (ASCII character 63) in the version returned by decoding the ASN.1; which may explain why Get-DateTime fails.

What's going on here?  More importantly, how can I get the string decoded from the ASN.1 to be a valid input to Get-DateTime?

Body:
The string returned by AsnEncodedData.Format() includes a bunch of Left-to-Right formatting characters. You can replace this with a simple regex:

$nextUpdateString = $extAsnDecoded.Format($false) -replace '\p{Cf}'

Cf is regex short-hand for the "Other, Format" unicode category, which will match (and remove) the formatting characters, after which you should be able to pass the string to Get-Date