问:
why is scanf skipping large part of input from file redirect? [C]
I have this program called simplechain.c here which basically has a program fork itself once, the child does the same and that keeps going a certain amount of times, then each process now (in reverse order due to a wait()) reads some amount of characters and prints them once they have enough:

```<code>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <getopt.h>
#include <errno.h>

// functiont that returns 0 (fail) if a string has anything but numbers 1 (success) if it all numbers
int isnumber(char * input){
        int length = strlen (input);
        int i;
        for (i = 0 ; i < length; i++)
        {
                if (!isdigit(input[i]))
                {
                        return 0;
                }
        }

        return 1;
}

int main (int argc, char *argv[]) {
        pid_t childpid = 0;
        int p;
        int nprocs = 4;
        int nchars = 80;
        int sleep_time = 3;
        int niters = 1;
        int opt;

        // argument handler
        while((opt = getopt(argc, argv, "hp:c:s:i:")) != -1)
        {
                switch(opt)
                {
                case 'h':       // help info
                         exit(0);
                        break;
                case 'p':       // set the amount of processes
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        nprocs = atoi(optarg); // store the specified number of processes
                        break;
                case 'c':       // set the amount of characters to be read
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        nchars = atoi(optarg); // store the specified number of character per interation to be read
                        break;
                case 's':       // set the amount of sleep time per interation
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        sleep_time = atoi(optarg); // store the specified nubmer of sleep time in seconds per interation
                        break;
                case 'i':       // set the amount of iterationc per print
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        niters = atoi(optarg); // store the specified number of interations to run on the print statments
                        break;
                }
        }
        // first start the for loop and fork if the current process number 'p' is less than the amount of processes
        for (p = 1; p < nprocs; p++)
                if ( (childpid = fork()) )
                        break;
        //sleep for 10 seconds
        sleep(10);

        // now print the process info 'niters' times
        int i;
        for(i = 0; i < niters; i++){
                wait(); // wait befor the prints

                fprintf(stderr, "i:%d ",p);                             // current process Number (not to be confused with ID)
                fprintf(stderr, " parent ID:%d ", (long)getppid());     // parent procsess ID
                fprintf(stderr, " child ID:%d ", (long)childpid);       // child process ID

                // now prompt the user for a certain amount (nchars) of characaters
                fprintf(stderr, "\nPlease enter %d characters pressing enter after each one: ", nchars);
                // read the input of each char and store in in the myBuf array
                char myBuf[nchars + 1];
                int c;

                for(c = 0; c < nchars; c++){
                        scanf(" %c", &myBuf[c]);
                }
                myBuf[nchars] = '\0';   // add the null terminator so that it becomes a valid string

                sleep(sleep_time);      // sleep for a certain amount of (sleep_time) seconds

                // finally print the current process ID followed by the string 'myBuf'
                fprintf(stderr, "process ID:%d;  '%s' \n", (long)getpid(), myBuf);
        }

        return 0;
}
</code>```

the point of interest is the loop using scanf(). its pretty simple as it just reads for a certain amount of characters and stores those characters into myBug array. you can obviously just do stdin but i was (which works fine btw) but i want to use a file so i did a file redirect given the fallowing file

```<code>In_Congress,_July_4,_1776_The_unanimous_Declaration_of_da_thirteen_united_States_of_America,_When_in_the_Course_of_human_events,_it_becomes_necessary_for_one_people_to_dissolve_the_political_bands_which_have_connected_them_with_another,_and_to_assume_among_the_powers_of_the_earth,_the_separate_and_equal_station_to_which_the_Laws_of_Nature_and_of_Nature's_God_entitle_them,_a_decent_respect_to_the_opinions_of_mankind_requires_that_they_should_declare_the_causes_which_impel_them_to_the_separation._We_hold_these_truths_to_be_self-evident,_that_all_men_are_created_equal,_that_they_are_endowed_by_their_Creator_with_certain_unalienable_Rights,_that_among_these_are_Life,_Liberty_and_the_pursuit_of_Happiness.--That_to_secure_these_rights,_Governments_are_instituted_among_Men,_deriving_their_just_powers_from_the_consent_of_the_governed,_--That_whenever_any_Form_of_Government_becomes_destructive_of_these_ends,_it_is_the_Right_of_the_People_to_alter_or_to_abolish_it,_and_to_institute_new_Government,_laying_its_foundation_on_such_principles_and_organizing_its_powers_in_such_form,_as_to_them_shall_seem_most_likely_to_effect_their_Safety_and_Happiness._Prudence,_indeed,_will_dictate_that_Governments_long_established_should_not_be_changed_for_light_and_transient_causes;_and_accordingly_all_experience_hath_shewn,_that_mankind_are_more_disposed_to_suffer,_while_evils_are_sufferable,_than_to_right_themselves_by_abolishing_the_forms_to_which_they_are_accustomed._But_when_a_long_train_of_abuses_and_usurpations,_pursuing_invariably_the_same_Object_evinces_a_design_to_reduce_them_under_absolute_Despotism,_it_is_their_right,_it_is_their_duty,_to_throw_off_such_Government,_and_to_provide_new_Guards_for_their_future_security.--Such_has_been_the_patient_sufferance_of_these_Colonies;_and_such_is_now_the_necessity_which_constrains_them_to_alter_their_former_Systems_of_Government._The_history_of_the_present_King_of_Great_Britain_is_a_history_of_repeated_injuries_and_usurpations,_all_having_in_direct_object_the_establishment_of_an_absolute_Tyranny_over_these_States._To_prove_this,_let_Facts_be_submitted_to_a_candid_world._He_has_refused_his_Assent_to_Laws,_the_most_wholesome_and_necessary_for_the_public_good._He_has_forbidden_his_Governors_to_pass_Laws_of_immediate_and_pressing_importance,_unless_suspended_in_their_operation_till_his_Assent_should_be_obtained;_and_when_so_suspended,_he_has_utterly_neglected_to_attend_to_them._He_has_refused_to_pass_other_Laws_for_the_accommodation_of_large_districts_of_people,_unless_those_people_would_relinquish_the_right_of_Representation_in_the_Legislature,_a_right_inestimable_to_them_and_formidable_to_tyrants_only._He_has_called_together_legislative_bodies_at_places_unusual,_uncomfortable,_and_distant_from_the_depository_of_their_public_Records,_for_the_sole_purpose_of_fatiguing_them_into_compliance_with_his_measures._He_has_dissolved_Representative_Houses_repeatedly,_for_opposing_with_manly_firmness_his_invasions_on_the_rights_of_the_people._He_has_refused_for_a_long_time,_after_such_dissolutions,_to_cause_others_to_be_elected;_whereby_the_Legislative_powers,_incapable_of_Annihilation,_have_returned_to_the_People_at_large_for_their_exercise;_the_State_remaining_in_the_mean_time_exposed_to_all_the_dangers_of_invasion_from_without,_and_convulsions_within._He_has_endeavoured_to_prevent_the_population_of_these_States;_for_that_purpose_obstructing_the_Laws_for_Naturalization_of_Foreigners;_refusing_to_pass_others_to_encourage_their_migrations_hither,_and_raising_the_conditions_of_new_Appropriations_of_Lands._He_has_obstructed_the_Administration_of_Justice,_by_refusing_his_Assent_to_Laws_for_establishing_Judiciary_powers._He_has_made_Judges_dependent_on_his_Will_alone,_for_the_tenure_of_their_offices,_and_the_amount_and_payment_of_their_salaries._He_has_erected_a_multitude_of_New_Offices,_and_sent_hither_swarms_of_Officers_to_harrass_our_people,_and_eat_out_their_substance._He_has_kept_among_us,_in_times_of_peace,_Standing_Armies_without_the_Consent_of_our_legislatures._He_has_affected_to_render_the_Military_independent_of_and_superior_to_the_Civil_power._He_has_combined_with_others_to_subject_us_to_a_jurisdiction_foreign_to_our_constitution,_and_unacknowledged_by_our_laws;_giving_his_Assent_to_their_Acts_of_pretended_Legislation:_For_Quartering_large_bodies_of_armed_troops_among_us:_For_protecting_them,_by_a_mock_Trial,_from_punishment_for_any_Murders_which_they_should_commit_on_the_Inhabitants_of_these_States:_For_cutting_off_our_Trade_with_all_parts_of_the_world:_For_imposing_Taxes_on_us_without_our_Consent:_For_depriving_us_in_many_cases,_of_the_benefits_of_Trial_by_Jury:_For_transporting_us_beyond_Seas_to_be_tried_for_pretended_offences_For_abolishing_the_free_System_of_English_Laws_in_a_neighbouring_Province,_establishing_therein_an_Arbitrary_government,_and_enlarging_its_Boundaries_so_as_to_render_it_at_once_an_example_and_fit_instrument_for_introducing_the_same_absolute_rule_into_these_Colonies:For_taking_away_our_Charters,_abolishing_our_most_valuable_Laws,_and_altering_fundamentally_the_Forms_of_our_Governments:_For_suspending_our_own_Legislatures,_and_declaring_themselves_invested_with_power_to_legislate_for_us_in_all_cases_whatsoever._He_has_abdicated_Government_here,_by_declaring_us_out_of_his_Protection_and_waging_War_against_us._He_has_plundered_our_seas,_ravaged_our_Coasts,_burnt_our_towns,_and_destroyed_the_lives_of_our_people._He_is_at_this_time_transporting_large_Armies_of_foreign_Mercenaries_to_compleat_the_works_of_death,_desolation_and_tyranny,_already_begun_with_circumstances_of_Cruelty_&_perfidy_scarcely_paralleled_in_the_most_barbarous_ages,_and_totally_unworthy_the_Head_of_a_civilized_nation._He_has_constrained_our_fellow_Citizens_taken_Captive_on_the_high_Seas_to_bear_Arms_against_their_Country,_to_become_the_executioners_of_their_friends_and_Brethren,_or_to_fall_themselves_by_their_Hands._He_has_excited_domestic_insurrections_amongst_us,_and_has_endeavoured_to_bring_on_the_inhabitants_of_our_frontiers,_the_merciless_Indian_Savages,_whose_known_rule_of_warfare,_is_an_undistinguished_destruction_of_all_ages,_sexes_and_conditions._In_every_stage_of_these_Oppressions_We_have_Petitioned_for_Redress_in_the_most_humble_terms:_Our_repeated_Petitions_have_been_answered_only_by_repeated_injury._A_Prince_whose_character_is_thus_marked_by_every_act_which_may_define_a_Tyrant,_is_unfit_to_be_the_ruler_of_a_free_people._Nor_have_We_been_wanting_in_attentions_to_our_Brittish_brethren._We_have_warned_them_from_time_to_time_of_attempts_by_their_legislature_to_extend_an_unwarrantable_jurisdiction_over_us._We_have_reminded_them_of_the_circumstances_of_our_emigration_and_settlement_here._We_have_appealed_to_their_native_justice_and_magnanimity,_and_we_have_conjured_them_by_the_ties_of_our_common_kindred_to_disavow_these_usurpations,_which,_would_inevitably_interrupt_our_connections_and_correspondence._They_too_have_been_deaf_to_the_voice_of_justice_and_of_consanguinity._We_must,_therefore,_acquiesce_in_the_necessity,_which_denounces_our_Separation,_and_hold_them,_as_we_hold_the_rest_of_mankind,_Enemies_in_War,_in_Peace_Friends._e,_therefore,_the_Representatives_of_the_united_States_of_America,_in_General_Congress,_Assembled,_appealing_to_the_Supreme_Judge_of_the_world_for_the_rectitude_of_our_intentions,_do,_in_the_Name,_and_by_Authority_of_the_good_People_of_these_Colonies,_solemnly_publish_and_declare,_That_these_United_Colonies_are,_and_of_Right_ought_to_be_Free_and_Independent_States;_that_they_are_Absolved_from_all_Allegiance_to_the_British_Crown,_and_that_all_political_connection_between_them_and_the_State_of_Great_Britain,_is_and_ought_to_be_totally_dissolved;_and_that_as_Free_and_Independent_States,_they_have_full_Power_to_levy_War,_conclude_Peace,_contract_Alliances,_establish_Commerce,_and_to_do_all_other_Acts_and_Things_which_Independent_States_may_of_right_do._And_for_the_support_of_this_Declaration,_with_a_firm_reliance_on_the_protection_of_divine_Providence,_we_mutually_pledge_to_each_other_our_Lives,_our_Fortunes_and_our_sacred_Honor._We,_therefore,_the_Representatives_of_the_united_States_of_America,_in_General_Congress,_Assembled,_appealing_to_the_Supreme_Judge_of_the_world_for_the_rectitude_of_our_intentions,_do,_in_the_Name,_and_by_Authority_of_the_good_People_of_these_Colonies,_solemnly_publish_and_declare,_That_these_United_Colonies_are,_and_of_Right_ought_to_be_Free_and_Independent_States;_that_they_are_Absolved_from_all_Allegiance_to_the_British_Crown,_and_that_all_political_connection_between_them_and_the_State_of_Great_Britain,_is_and_ought_to_be_totally_dissolved;_and_that_as_Free_and_Independent_States,_they_have_full_Power_to_levy_War,_conclude_Peace,_contract_Alliances,_establish_Commerce,_and_to_do_all_other_Acts_and_Things_which_Independent_States_may_of_right_do._And_for_the_support_of_this_Declaration,_with_a_firm_reliance_on_the_protection_of_divine_Providence,_we_mutually_pledge_to_each_other_our_Lives,_our_Fortunes_and_our_sacred_Honor.
</code>```

this is just a long file containing the declaration of independence

But when i run the fallowing command : $ ./myapp -p 5 -c 30 -s 1 -i 2 < dc.txt
this command should cause the program to make 4 forks each looping its print statements 2 and requiring 30 characters to be read per loop
i get the fallowing output :

```<code>i:5  parent ID:29725  child ID:0
Please enter 30 characters pressing enter after each one: process ID:29726;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:29725  child ID:0
Please enter 30 characters pressing enter after each one: process ID:29726;  'unanimous_Declaration_of_da_th'
i:4  parent ID:29724  child ID:29726
Please enter 30 characters pressing enter after each one: process ID:29725;  't_of_and_superior_to_the_Civil'
i:4  parent ID:29724  child ID:29726
Please enter 30 characters pressing enter after each one: process ID:29725;  '_power._He_has_combined_with_o'
i:3  parent ID:29723  child ID:29725
Please enter 30 characters pressing enter after each one: process ID:29724;  'Congress,_Assembled,_appealing'
i:3  parent ID:29723  child ID:29725
Please enter 30 characters pressing enter after each one: process ID:29724;  '_to_the_Supreme_Judge_of_the_w'
i:2  parent ID:29722  child ID:29724
Please enter 30 characters pressing enter after each one: process ID:29723;  ''
i:2  parent ID:29722  child ID:29724
Please enter 30 characters pressing enter after each one: process ID:29723;  ''
i:1  parent ID:24839  child ID:29723
Please enter 30 characters pressing enter after each one: process ID:29722;  ''
i:1  parent ID:24839  child ID:29723
Please enter 30 characters pressing enter after each one: process ID:29722;  ''
</code>```

I know the file has enough characters for sure. and it works fine for the first few processes.
But if you look at the actual words being read you notice a skip in the text between processes. And finally the last 2 processes don't get any characters at all. My guess is process 5 reads twice then process 4 skips later on in the text for reads twice again, process 3 does the same and by the time it gets to process 2 and 1 it already reached the end of the file. I'm not sure why it is skipping.

答:
The short answer is Buffered I/O.

The programs all share the same file stream.  Reading from a file, the first process to read the file gets a block of data (probably 512 or 4096 bytes) which the others don't see, but the file read position for the others moves.  Rinse and repeat.  If you used file descriptor I/O, you wouldn't get the same buffering effect.  If you read some data using file streams before you did the forking, you'd get another set of results (all showing the same data).  If the input was not a file but a pipe or something else, you'd get other results again.

You could probably fix it by setting the buffer size small, or unbuffered:

```<code>setvbuf(stdin, NULL, _IONBF, 0);
</code>```

before doing any input.

Here's an adaptation of your code with an extra option -u to make standard input unbuffered and another option -P to suppress prompting.  Note that I had to rename the function isnumber() to is_number() to avoid a name collision with the <ctype.h> header on my Mac — the name isnumber() is reserved for the implementation.

#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static int is_number(char *input)
{
    int length = strlen(input);
    int i;
    for (i = 0; i < length; i++)
    {
        if (!isdigit(input[i]))
        {
            return 0;
        }
    }

    return 1;
}

int main(int argc, char *argv[])
{
    pid_t childpid = 0;
    int p;
    int nprocs = 4;
    int nchars = 80;
    int sleep_time = 3;
    int niters = 1;
    int buffered = 1;
    int prompt = 1;
    int opt;

    while ((opt = getopt(argc, argv, "Puhp:c:s:i:")) != -1)
    {
        switch (opt)
        {
        case 'h':
            exit(0);
            break;
        case 'p':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            nprocs = atoi(optarg);
            break;
        case 'c':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            nchars = atoi(optarg);
            break;
        case 's':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            sleep_time = atoi(optarg);
            break;
        case 'i':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            niters = atoi(optarg);
            break;
        case 'u':
            buffered = 0;
            break;
        case 'P':
            prompt = 0;
            break;
        default:
            fprintf(stderr, "Unexpected option '%c'\n", opt);
            exit(EXIT_FAILURE);
        }
    }

    if (buffered)
    {
        fprintf(stderr, "Buffered input\n");
        setvbuf(stdin, NULL, _IOFBF, 0);
    }
    else
    {
        fprintf(stderr, "Unbuffered input\n");
        setvbuf(stdin, NULL, _IONBF, 0);
    }

    for (p = 1; p < nprocs; p++)
    {
        if ((childpid = fork()))
            break;
    }

    sleep(2);

    for (int i = 0; i < niters; i++)
    {
        int status;
        int corpse;
        while ((corpse = wait(&status)) > 0)
        {
            fprintf(stderr, "%d: child %d exited with status 0x%.4X\n",
                    getpid(), corpse, status);
        }

        fprintf(stderr, "i:%d ", p);
        fprintf(stderr, " parent ID:%d ", getppid());
        fprintf(stderr, " child ID:%d\n", childpid);

        if (prompt)
        {
            fprintf(stderr, "Please enter %d characters pressing enter after each one: ",
                    nchars);
        }

        char myBuf[nchars + 1];
        int c;

        for (c = 0; c < nchars; c++)
        {
            scanf(" %c", &myBuf[c]);
        }
        myBuf[nchars] = '\0';

        sleep(sleep_time);

        fprintf(stderr, "process ID: %d;  '%s'\n", getpid(), myBuf);
    }

    return 0;
}
```
<p>When run on a Mac, I get the desired behaviour whether or not standard input is buffered.  When run on RHEL 7.4 Linux, the buffered/unbuffered I/O matters.  The source code was in <code>rd31.c</code> and was compiled to create <code>rd31</code>.</p>
<pre class="lang-none prettyprint-override"><code>$ make rd31
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wstrict-prototypes -Wmissing-prototypes -Wshadow -pedantic-errors rd31.c -o rd31
$ rd31 -P -u -p 5 -c 30 -s 1 -i 2 < dec-independence
Unbuffered input
i:5  parent ID:4462  child ID:0
process ID: 4463;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:4462  child ID:0
process ID: 4463;  'unanimous_Declaration_of_da_th'
4462: child 4463 exited with status 0x0000
i:4  parent ID:4460  child ID:4463
process ID: 4462;  'irteen_united_States_of_Americ'
i:4  parent ID:4460  child ID:4463
process ID: 4462;  'a,_When_in_the_Course_of_human'
4460: child 4462 exited with status 0x0000
i:3  parent ID:4459  child ID:4462
process ID: 4460;  '_events,_it_becomes_necessary_'
i:3  parent ID:4459  child ID:4462
process ID: 4460;  'for_one_people_to_dissolve_the'
4459: child 4460 exited with status 0x0000
i:2  parent ID:4457  child ID:4460
process ID: 4459;  '_political_bands_which_have_co'
i:2  parent ID:4457  child ID:4460
process ID: 4459;  'nnected_them_with_another,_and'
4457: child 4459 exited with status 0x0000
i:1  parent ID:9082  child ID:4459
process ID: 4457;  '_to_assume_among_the_powers_of'
i:1  parent ID:9082  child ID:4459
process ID: 4457;  '_the_earth,_the_separate_and_e'
$ rd31 -P -p 5 -c 30 -s 1 -i 2 < dec-independence
Buffered input
i:5  parent ID:4491  child ID:0
process ID: 4492;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:4491  child ID:0
process ID: 4492;  'unanimous_Declaration_of_da_th'
4491: child 4492 exited with status 0x0000
i:4  parent ID:4490  child ID:4492
process ID: 4491;  't_of_and_superior_to_the_Civil'
i:4  parent ID:4490  child ID:4492
process ID: 4491;  '_power._He_has_combined_with_o'
4490: child 4491 exited with status 0x0000
i:3  parent ID:4489  child ID:4491
process ID: 4490;  'Congress,_Assembled,_appealing'
i:3  parent ID:4489  child ID:4491
process ID: 4490;  '_to_the_Supreme_Judge_of_the_w'
4489: child 4490 exited with status 0x0000
i:2  parent ID:4487  child ID:4490
process ID: 4489;  ''
i:2  parent ID:4487  child ID:4490
process ID: 4489;  ''
4487: child 4489 exited with status 0x0000
i:1  parent ID:9082  child ID:4489
process ID: 4487;  ''
i:1  parent ID:9082  child ID:4489
$
</code>```

Body:
I have this program called simplechain.c here which basically has a program fork itself once, the child does the same and that keeps going a certain amount of times, then each process now (in reverse order due to a wait()) reads some amount of characters and prints them once they have enough:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <getopt.h>
#include <errno.h>

// functiont that returns 0 (fail) if a string has anything but numbers 1 (success) if it all numbers
int isnumber(char * input){
        int length = strlen (input);
        int i;
        for (i = 0 ; i < length; i++)
        {
                if (!isdigit(input[i]))
                {
                        return 0;
                }
        }

        return 1;
}

int main (int argc, char *argv[]) {
        pid_t childpid = 0;
        int p;
        int nprocs = 4;
        int nchars = 80;
        int sleep_time = 3;
        int niters = 1;
        int opt;

        // argument handler
        while((opt = getopt(argc, argv, "hp:c:s:i:")) != -1)
        {
                switch(opt)
                {
                case 'h':       // help info
                         exit(0);
                        break;
                case 'p':       // set the amount of processes
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        nprocs = atoi(optarg); // store the specified number of processes
                        break;
                case 'c':       // set the amount of characters to be read
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        nchars = atoi(optarg); // store the specified number of character per interation to be read
                        break;
                case 's':       // set the amount of sleep time per interation
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        sleep_time = atoi(optarg); // store the specified nubmer of sleep time in seconds per interation
                        break;
                case 'i':       // set the amount of iterationc per print
                        if(!isnumber(optarg)){
                                exit(-1);
                        }
                        niters = atoi(optarg); // store the specified number of interations to run on the print statments
                        break;
                }
        }
        // first start the for loop and fork if the current process number 'p' is less than the amount of processes
        for (p = 1; p < nprocs; p++)
                if ( (childpid = fork()) )
                        break;
        //sleep for 10 seconds
        sleep(10);

        // now print the process info 'niters' times
        int i;
        for(i = 0; i < niters; i++){
                wait(); // wait befor the prints

                fprintf(stderr, "i:%d ",p);                             // current process Number (not to be confused with ID)
                fprintf(stderr, " parent ID:%d ", (long)getppid());     // parent procsess ID
                fprintf(stderr, " child ID:%d ", (long)childpid);       // child process ID

                // now prompt the user for a certain amount (nchars) of characaters
                fprintf(stderr, "\nPlease enter %d characters pressing enter after each one: ", nchars);
                // read the input of each char and store in in the myBuf array
                char myBuf[nchars + 1];
                int c;

                for(c = 0; c < nchars; c++){
                        scanf(" %c", &myBuf[c]);
                }
                myBuf[nchars] = '\0';   // add the null terminator so that it becomes a valid string

                sleep(sleep_time);      // sleep for a certain amount of (sleep_time) seconds

                // finally print the current process ID followed by the string 'myBuf'
                fprintf(stderr, "process ID:%d;  '%s' \n", (long)getpid(), myBuf);
        }

        return 0;
}

the point of interest is the loop using scanf(). its pretty simple as it just reads for a certain amount of characters and stores those characters into myBug array. you can obviously just do stdin but i was (which works fine btw) but i want to use a file so i did a file redirect given the fallowing file

In_Congress,_July_4,_1776_The_unanimous_Declaration_of_da_thirteen_united_States_of_America,_When_in_the_Course_of_human_events,_it_becomes_necessary_for_one_people_to_dissolve_the_political_bands_which_have_connected_them_with_another,_and_to_assume_among_the_powers_of_the_earth,_the_separate_and_equal_station_to_which_the_Laws_of_Nature_and_of_Nature's_God_entitle_them,_a_decent_respect_to_the_opinions_of_mankind_requires_that_they_should_declare_the_causes_which_impel_them_to_the_separation._We_hold_these_truths_to_be_self-evident,_that_all_men_are_created_equal,_that_they_are_endowed_by_their_Creator_with_certain_unalienable_Rights,_that_among_these_are_Life,_Liberty_and_the_pursuit_of_Happiness.--That_to_secure_these_rights,_Governments_are_instituted_among_Men,_deriving_their_just_powers_from_the_consent_of_the_governed,_--That_whenever_any_Form_of_Government_becomes_destructive_of_these_ends,_it_is_the_Right_of_the_People_to_alter_or_to_abolish_it,_and_to_institute_new_Government,_laying_its_foundation_on_such_principles_and_organizing_its_powers_in_such_form,_as_to_them_shall_seem_most_likely_to_effect_their_Safety_and_Happiness._Prudence,_indeed,_will_dictate_that_Governments_long_established_should_not_be_changed_for_light_and_transient_causes;_and_accordingly_all_experience_hath_shewn,_that_mankind_are_more_disposed_to_suffer,_while_evils_are_sufferable,_than_to_right_themselves_by_abolishing_the_forms_to_which_they_are_accustomed._But_when_a_long_train_of_abuses_and_usurpations,_pursuing_invariably_the_same_Object_evinces_a_design_to_reduce_them_under_absolute_Despotism,_it_is_their_right,_it_is_their_duty,_to_throw_off_such_Government,_and_to_provide_new_Guards_for_their_future_security.--Such_has_been_the_patient_sufferance_of_these_Colonies;_and_such_is_now_the_necessity_which_constrains_them_to_alter_their_former_Systems_of_Government._The_history_of_the_present_King_of_Great_Britain_is_a_history_of_repeated_injuries_and_usurpations,_all_having_in_direct_object_the_establishment_of_an_absolute_Tyranny_over_these_States._To_prove_this,_let_Facts_be_submitted_to_a_candid_world._He_has_refused_his_Assent_to_Laws,_the_most_wholesome_and_necessary_for_the_public_good._He_has_forbidden_his_Governors_to_pass_Laws_of_immediate_and_pressing_importance,_unless_suspended_in_their_operation_till_his_Assent_should_be_obtained;_and_when_so_suspended,_he_has_utterly_neglected_to_attend_to_them._He_has_refused_to_pass_other_Laws_for_the_accommodation_of_large_districts_of_people,_unless_those_people_would_relinquish_the_right_of_Representation_in_the_Legislature,_a_right_inestimable_to_them_and_formidable_to_tyrants_only._He_has_called_together_legislative_bodies_at_places_unusual,_uncomfortable,_and_distant_from_the_depository_of_their_public_Records,_for_the_sole_purpose_of_fatiguing_them_into_compliance_with_his_measures._He_has_dissolved_Representative_Houses_repeatedly,_for_opposing_with_manly_firmness_his_invasions_on_the_rights_of_the_people._He_has_refused_for_a_long_time,_after_such_dissolutions,_to_cause_others_to_be_elected;_whereby_the_Legislative_powers,_incapable_of_Annihilation,_have_returned_to_the_People_at_large_for_their_exercise;_the_State_remaining_in_the_mean_time_exposed_to_all_the_dangers_of_invasion_from_without,_and_convulsions_within._He_has_endeavoured_to_prevent_the_population_of_these_States;_for_that_purpose_obstructing_the_Laws_for_Naturalization_of_Foreigners;_refusing_to_pass_others_to_encourage_their_migrations_hither,_and_raising_the_conditions_of_new_Appropriations_of_Lands._He_has_obstructed_the_Administration_of_Justice,_by_refusing_his_Assent_to_Laws_for_establishing_Judiciary_powers._He_has_made_Judges_dependent_on_his_Will_alone,_for_the_tenure_of_their_offices,_and_the_amount_and_payment_of_their_salaries._He_has_erected_a_multitude_of_New_Offices,_and_sent_hither_swarms_of_Officers_to_harrass_our_people,_and_eat_out_their_substance._He_has_kept_among_us,_in_times_of_peace,_Standing_Armies_without_the_Consent_of_our_legislatures._He_has_affected_to_render_the_Military_independent_of_and_superior_to_the_Civil_power._He_has_combined_with_others_to_subject_us_to_a_jurisdiction_foreign_to_our_constitution,_and_unacknowledged_by_our_laws;_giving_his_Assent_to_their_Acts_of_pretended_Legislation:_For_Quartering_large_bodies_of_armed_troops_among_us:_For_protecting_them,_by_a_mock_Trial,_from_punishment_for_any_Murders_which_they_should_commit_on_the_Inhabitants_of_these_States:_For_cutting_off_our_Trade_with_all_parts_of_the_world:_For_imposing_Taxes_on_us_without_our_Consent:_For_depriving_us_in_many_cases,_of_the_benefits_of_Trial_by_Jury:_For_transporting_us_beyond_Seas_to_be_tried_for_pretended_offences_For_abolishing_the_free_System_of_English_Laws_in_a_neighbouring_Province,_establishing_therein_an_Arbitrary_government,_and_enlarging_its_Boundaries_so_as_to_render_it_at_once_an_example_and_fit_instrument_for_introducing_the_same_absolute_rule_into_these_Colonies:For_taking_away_our_Charters,_abolishing_our_most_valuable_Laws,_and_altering_fundamentally_the_Forms_of_our_Governments:_For_suspending_our_own_Legislatures,_and_declaring_themselves_invested_with_power_to_legislate_for_us_in_all_cases_whatsoever._He_has_abdicated_Government_here,_by_declaring_us_out_of_his_Protection_and_waging_War_against_us._He_has_plundered_our_seas,_ravaged_our_Coasts,_burnt_our_towns,_and_destroyed_the_lives_of_our_people._He_is_at_this_time_transporting_large_Armies_of_foreign_Mercenaries_to_compleat_the_works_of_death,_desolation_and_tyranny,_already_begun_with_circumstances_of_Cruelty_&_perfidy_scarcely_paralleled_in_the_most_barbarous_ages,_and_totally_unworthy_the_Head_of_a_civilized_nation._He_has_constrained_our_fellow_Citizens_taken_Captive_on_the_high_Seas_to_bear_Arms_against_their_Country,_to_become_the_executioners_of_their_friends_and_Brethren,_or_to_fall_themselves_by_their_Hands._He_has_excited_domestic_insurrections_amongst_us,_and_has_endeavoured_to_bring_on_the_inhabitants_of_our_frontiers,_the_merciless_Indian_Savages,_whose_known_rule_of_warfare,_is_an_undistinguished_destruction_of_all_ages,_sexes_and_conditions._In_every_stage_of_these_Oppressions_We_have_Petitioned_for_Redress_in_the_most_humble_terms:_Our_repeated_Petitions_have_been_answered_only_by_repeated_injury._A_Prince_whose_character_is_thus_marked_by_every_act_which_may_define_a_Tyrant,_is_unfit_to_be_the_ruler_of_a_free_people._Nor_have_We_been_wanting_in_attentions_to_our_Brittish_brethren._We_have_warned_them_from_time_to_time_of_attempts_by_their_legislature_to_extend_an_unwarrantable_jurisdiction_over_us._We_have_reminded_them_of_the_circumstances_of_our_emigration_and_settlement_here._We_have_appealed_to_their_native_justice_and_magnanimity,_and_we_have_conjured_them_by_the_ties_of_our_common_kindred_to_disavow_these_usurpations,_which,_would_inevitably_interrupt_our_connections_and_correspondence._They_too_have_been_deaf_to_the_voice_of_justice_and_of_consanguinity._We_must,_therefore,_acquiesce_in_the_necessity,_which_denounces_our_Separation,_and_hold_them,_as_we_hold_the_rest_of_mankind,_Enemies_in_War,_in_Peace_Friends._e,_therefore,_the_Representatives_of_the_united_States_of_America,_in_General_Congress,_Assembled,_appealing_to_the_Supreme_Judge_of_the_world_for_the_rectitude_of_our_intentions,_do,_in_the_Name,_and_by_Authority_of_the_good_People_of_these_Colonies,_solemnly_publish_and_declare,_That_these_United_Colonies_are,_and_of_Right_ought_to_be_Free_and_Independent_States;_that_they_are_Absolved_from_all_Allegiance_to_the_British_Crown,_and_that_all_political_connection_between_them_and_the_State_of_Great_Britain,_is_and_ought_to_be_totally_dissolved;_and_that_as_Free_and_Independent_States,_they_have_full_Power_to_levy_War,_conclude_Peace,_contract_Alliances,_establish_Commerce,_and_to_do_all_other_Acts_and_Things_which_Independent_States_may_of_right_do._And_for_the_support_of_this_Declaration,_with_a_firm_reliance_on_the_protection_of_divine_Providence,_we_mutually_pledge_to_each_other_our_Lives,_our_Fortunes_and_our_sacred_Honor._We,_therefore,_the_Representatives_of_the_united_States_of_America,_in_General_Congress,_Assembled,_appealing_to_the_Supreme_Judge_of_the_world_for_the_rectitude_of_our_intentions,_do,_in_the_Name,_and_by_Authority_of_the_good_People_of_these_Colonies,_solemnly_publish_and_declare,_That_these_United_Colonies_are,_and_of_Right_ought_to_be_Free_and_Independent_States;_that_they_are_Absolved_from_all_Allegiance_to_the_British_Crown,_and_that_all_political_connection_between_them_and_the_State_of_Great_Britain,_is_and_ought_to_be_totally_dissolved;_and_that_as_Free_and_Independent_States,_they_have_full_Power_to_levy_War,_conclude_Peace,_contract_Alliances,_establish_Commerce,_and_to_do_all_other_Acts_and_Things_which_Independent_States_may_of_right_do._And_for_the_support_of_this_Declaration,_with_a_firm_reliance_on_the_protection_of_divine_Providence,_we_mutually_pledge_to_each_other_our_Lives,_our_Fortunes_and_our_sacred_Honor.

this is just a long file containing the declaration of independence

But when i run the fallowing command : $ ./myapp -p 5 -c 30 -s 1 -i 2 < dc.txt
this command should cause the program to make 4 forks each looping its print statements 2 and requiring 30 characters to be read per loop
i get the fallowing output :

i:5  parent ID:29725  child ID:0
Please enter 30 characters pressing enter after each one: process ID:29726;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:29725  child ID:0
Please enter 30 characters pressing enter after each one: process ID:29726;  'unanimous_Declaration_of_da_th'
i:4  parent ID:29724  child ID:29726
Please enter 30 characters pressing enter after each one: process ID:29725;  't_of_and_superior_to_the_Civil'
i:4  parent ID:29724  child ID:29726
Please enter 30 characters pressing enter after each one: process ID:29725;  '_power._He_has_combined_with_o'
i:3  parent ID:29723  child ID:29725
Please enter 30 characters pressing enter after each one: process ID:29724;  'Congress,_Assembled,_appealing'
i:3  parent ID:29723  child ID:29725
Please enter 30 characters pressing enter after each one: process ID:29724;  '_to_the_Supreme_Judge_of_the_w'
i:2  parent ID:29722  child ID:29724
Please enter 30 characters pressing enter after each one: process ID:29723;  ''
i:2  parent ID:29722  child ID:29724
Please enter 30 characters pressing enter after each one: process ID:29723;  ''
i:1  parent ID:24839  child ID:29723
Please enter 30 characters pressing enter after each one: process ID:29722;  ''
i:1  parent ID:24839  child ID:29723
Please enter 30 characters pressing enter after each one: process ID:29722;  ''

I know the file has enough characters for sure. and it works fine for the first few processes.
But if you look at the actual words being read you notice a skip in the text between processes. And finally the last 2 processes don't get any characters at all. My guess is process 5 reads twice then process 4 skips later on in the text for reads twice again, process 3 does the same and by the time it gets to process 2 and 1 it already reached the end of the file. I'm not sure why it is skipping.

Body:
The short answer is Buffered I/O.

The programs all share the same file stream.  Reading from a file, the first process to read the file gets a block of data (probably 512 or 4096 bytes) which the others don't see, but the file read position for the others moves.  Rinse and repeat.  If you used file descriptor I/O, you wouldn't get the same buffering effect.  If you read some data using file streams before you did the forking, you'd get another set of results (all showing the same data).  If the input was not a file but a pipe or something else, you'd get other results again.

You could probably fix it by setting the buffer size small, or unbuffered:

setvbuf(stdin, NULL, _IONBF, 0);

before doing any input.

Here's an adaptation of your code with an extra option -u to make standard input unbuffered and another option -P to suppress prompting.  Note that I had to rename the function isnumber() to is_number() to avoid a name collision with the <ctype.h> header on my Mac — the name isnumber() is reserved for the implementation.

#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

static int is_number(char *input)
{
    int length = strlen(input);
    int i;
    for (i = 0; i < length; i++)
    {
        if (!isdigit(input[i]))
        {
            return 0;
        }
    }

    return 1;
}

int main(int argc, char *argv[])
{
    pid_t childpid = 0;
    int p;
    int nprocs = 4;
    int nchars = 80;
    int sleep_time = 3;
    int niters = 1;
    int buffered = 1;
    int prompt = 1;
    int opt;

    while ((opt = getopt(argc, argv, "Puhp:c:s:i:")) != -1)
    {
        switch (opt)
        {
        case 'h':
            exit(0);
            break;
        case 'p':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            nprocs = atoi(optarg);
            break;
        case 'c':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            nchars = atoi(optarg);
            break;
        case 's':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            sleep_time = atoi(optarg);
            break;
        case 'i':
            if (!is_number(optarg))
            {
                exit(-1);
            }
            niters = atoi(optarg);
            break;
        case 'u':
            buffered = 0;
            break;
        case 'P':
            prompt = 0;
            break;
        default:
            fprintf(stderr, "Unexpected option '%c'\n", opt);
            exit(EXIT_FAILURE);
        }
    }

    if (buffered)
    {
        fprintf(stderr, "Buffered input\n");
        setvbuf(stdin, NULL, _IOFBF, 0);
    }
    else
    {
        fprintf(stderr, "Unbuffered input\n");
        setvbuf(stdin, NULL, _IONBF, 0);
    }

    for (p = 1; p < nprocs; p++)
    {
        if ((childpid = fork()))
            break;
    }

    sleep(2);

    for (int i = 0; i < niters; i++)
    {
        int status;
        int corpse;
        while ((corpse = wait(&status)) > 0)
        {
            fprintf(stderr, "%d: child %d exited with status 0x%.4X\n",
                    getpid(), corpse, status);
        }

        fprintf(stderr, "i:%d ", p);
        fprintf(stderr, " parent ID:%d ", getppid());
        fprintf(stderr, " child ID:%d\n", childpid);

        if (prompt)
        {
            fprintf(stderr, "Please enter %d characters pressing enter after each one: ",
                    nchars);
        }

        char myBuf[nchars + 1];
        int c;

        for (c = 0; c < nchars; c++)
        {
            scanf(" %c", &myBuf[c]);
        }
        myBuf[nchars] = '\0';

        sleep(sleep_time);

        fprintf(stderr, "process ID: %d;  '%s'\n", getpid(), myBuf);
    }

    return 0;
}

When run on a Mac, I get the desired behaviour whether or not standard input is buffered.  When run on RHEL 7.4 Linux, the buffered/unbuffered I/O matters.  The source code was in rd31.c and was compiled to create rd31.

$ make rd31
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wstrict-prototypes -Wmissing-prototypes -Wshadow -pedantic-errors rd31.c -o rd31
$ rd31 -P -u -p 5 -c 30 -s 1 -i 2 < dec-independence
Unbuffered input
i:5  parent ID:4462  child ID:0
process ID: 4463;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:4462  child ID:0
process ID: 4463;  'unanimous_Declaration_of_da_th'
4462: child 4463 exited with status 0x0000
i:4  parent ID:4460  child ID:4463
process ID: 4462;  'irteen_united_States_of_Americ'
i:4  parent ID:4460  child ID:4463
process ID: 4462;  'a,_When_in_the_Course_of_human'
4460: child 4462 exited with status 0x0000
i:3  parent ID:4459  child ID:4462
process ID: 4460;  '_events,_it_becomes_necessary_'
i:3  parent ID:4459  child ID:4462
process ID: 4460;  'for_one_people_to_dissolve_the'
4459: child 4460 exited with status 0x0000
i:2  parent ID:4457  child ID:4460
process ID: 4459;  '_political_bands_which_have_co'
i:2  parent ID:4457  child ID:4460
process ID: 4459;  'nnected_them_with_another,_and'
4457: child 4459 exited with status 0x0000
i:1  parent ID:9082  child ID:4459
process ID: 4457;  '_to_assume_among_the_powers_of'
i:1  parent ID:9082  child ID:4459
process ID: 4457;  '_the_earth,_the_separate_and_e'
$ rd31 -P -p 5 -c 30 -s 1 -i 2 < dec-independence
Buffered input
i:5  parent ID:4491  child ID:0
process ID: 4492;  'In_Congress,_July_4,_1776_The_'
i:5  parent ID:4491  child ID:0
process ID: 4492;  'unanimous_Declaration_of_da_th'
4491: child 4492 exited with status 0x0000
i:4  parent ID:4490  child ID:4492
process ID: 4491;  't_of_and_superior_to_the_Civil'
i:4  parent ID:4490  child ID:4492
process ID: 4491;  '_power._He_has_combined_with_o'
4490: child 4491 exited with status 0x0000
i:3  parent ID:4489  child ID:4491
process ID: 4490;  'Congress,_Assembled,_appealing'
i:3  parent ID:4489  child ID:4491
process ID: 4490;  '_to_the_Supreme_Judge_of_the_w'
4489: child 4490 exited with status 0x0000
i:2  parent ID:4487  child ID:4490
process ID: 4489;  ''
i:2  parent ID:4487  child ID:4490
process ID: 4489;  ''
4487: child 4489 exited with status 0x0000
i:1  parent ID:9082  child ID:4489
process ID: 4487;  ''
i:1  parent ID:9082  child ID:4489
$


来源: stackexchange

问:
Bootstrap 4 - large rounded corners only on top half
In Bootstrap 4, they have the classes .rounded-top and .rounded-lg I want to be able to create a large rounded corner on only the top half. If I add .rounded-top it rounds just the top which is what I want, but I also want it to be large. If I add .rounded-lg it rounds all the corners.

How can I round just the top with a large round?

答:
You can try global classes:</p>
```<code> .rounded-top-left {
        border-top-left-radius: 2rem;
    }
    .rounded-top-right {
        border-top-right-radius: 2rem;
    }
    .rounded-bottom-left {
        border-bottom-left-radius: 2rem;
    }
    .rounded-bottom-right {
        border-bottom-right-radius: 2rem;
    }
</code>```

ContentLicense: CC BY-SA 4.0

Body:
You can try global classes:

 .rounded-top-left {
        border-top-left-radius: 2rem;
    }
    .rounded-top-right {
        border-top-right-radius: 2rem;
    }
    .rounded-bottom-left {
        border-bottom-left-radius: 2rem;
    }
    .rounded-bottom-right {
        border-bottom-right-radius: 2rem;
    }


问:
UUID breaking the ws connect
I've been using a websockets connection with django-channels for a chatroom app with the following routing:

```<code>    re_path(r'ws/chat/(?P<room_name>\w+)/participant/(?P<user>\w+)/$', consumers.ChatConsumer.as_asgi())
</code>```

So if the id of my chatroom is 1, to connect to WS I would use the following url with 2 being the id of the participant that wants to enter the room:

```<code>ws/chat/1/participant/1/
</code>```

Now i changed the id of my room model to UUID so now to connect to a room I need to use the following url

```<code>ws/chat/84f48468-e966-46e9-a46c-67920026d669/participant/1/
</code>```

where "84f48468-e966-46e9-a46c-67920026d669" is the id of my room now, but I'm getting the following error:

```<code>raise ValueError("No route found for path %r." % path)
ValueError: No route found for path 'ws/chat/84f48468-e966-46e9-a46c-
67920026d669/participant/1/'.
WebSocket DISCONNECT /ws/chat/84f48468-e966-46e9-a46c-67920026d669/participant/1/
[127.0.0.1:50532]
</code>```

My consumers:

```<code>class ChatConsumer(WebsocketConsumer):
def connect(self):
    self.room_name = self.scope['url_route']['kwargs']['room_name']
    self.user = self.scope['url_route']['kwargs']['user']
    self.room_group_name = 'chat_%s' % self.room_name

    # Join room group
    async_to_sync(self.channel_layer.group_add)(
        self.room_group_name,
        self.channel_name
    )

    self.accept()

def disconnect(self, close_code):
    delete = delete_participant(self.room_name, self.user)
    if delete == 'not_can_delete_user':
        pass
    else:
        # Leave room group
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            f'chat_{self.room_name}',
            {
                'type': 'receive',
                'message': "USER_DISCONNECT",
                'body': {
                    'participant': delete,
                    'idParticipant': self.user
                }
            }
        )

    async_to_sync(self.channel_layer.group_discard)(
        self.room_group_name,
        self.channel_name
    )

def receive(self, text_data=None, type='receive', **kwargs):
    if isinstance(text_data, dict):
        text_data_json = text_data

        message = text_data_json['message']
        body = text_data_json['body']
    else:
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        body = text_data_json['body']

    self.send(text_data=json.dumps({
        'message': message,
        "body": body

        }))

</code>```

What is wrong?

答:
try this regex:</p>
```<code> re_path(r'ws/chat/(?P<room_name>[A-Za-z0-9_-]+)....
</code>```

Title: UUID breaking the ws connect

Body:
I've been using a websockets connection with django-channels for a chatroom app with the following routing:

    re_path(r'ws/chat/(?P<room_name>\w+)/participant/(?P<user>\w+)/$', consumers.ChatConsumer.as_asgi())

So if the id of my chatroom is 1, to connect to WS I would use the following url with 2 being the id of the participant that wants to enter the room:

ws/chat/1/participant/1/

Now i changed the id of my room model to UUID so now to connect to a room I need to use the following url

ws/chat/84f48468-e966-46e9-a46c-67920026d669/participant/1/

where "84f48468-e966-46e9-a46c-67920026d669" is the id of my room now, but I'm getting the following error:

raise ValueError("No route found for path %r." % path)
ValueError: No route found for path 'ws/chat/84f48468-e966-46e9-a46c-
67920026d669/participant/1/'.
WebSocket DISCONNECT /ws/chat/84f48468-e966-46e9-a46c-67920026d669/participant/1/
[127.0.0.1:50532]

My consumers:

class ChatConsumer(WebsocketConsumer):
def connect(self):
    self.room_name = self.scope['url_route']['kwargs']['room_name']
    self.user = self.scope['url_route']['kwargs']['user']
    self.room_group_name = 'chat_%s' % self.room_name

    # Join room group
    async_to_sync(self.channel_layer.group_add)(
        self.room_group_name,
        self.channel_name
    )

    self.accept()

def disconnect(self, close_code):
    delete = delete_participant(self.room_name, self.user)
    if delete == 'not_can_delete_user':
        pass
    else:
        # Leave room group
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            f'chat_{self.room_name}',
            {
                'type': 'receive',
                'message': "USER_DISCONNECT",
                'body': {
                    'participant': delete,
                    'idParticipant': self.user
                }
            }
        )

    async_to_sync(self.channel_layer.group_discard)(
        self.room_group_name,
        self.channel_name
    )

def receive(self, text_data=None, type='receive', **kwargs):
    if isinstance(text_data, dict):
        text_data_json = text_data

        message = text_data_json['message']
        body = text_data_json['body']
    else:
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        body = text_data_json['body']

    self.send(text_data=json.dumps({
        'message': message,
        "body": body

        }))

What is wrong?

Body:
try this regex:

 re_path(r'ws/chat/(?P<room_name>[A-Za-z0-9_-]+)....


问:
Convert a list of day/opening hours to a more readable format
I have a silly little problem I'm having some difficulty getting a neat solution for. All I try turns messy and too complicated very quickly.

The problem is this.
Given a list of key value pair like:

"Mon", "09:00-17:00"

"Tue", "09:00-17:00"

"Wed", "09:00-17:00"

"Thu", "08:00-18:00"

"Fri", "09:00-17:00"

We should return a simplified list that looks like this

"Mon-Wed", "09:00-17:00"

"Thu", "08:00-18:00"

"Fri", "09:00-17:00"

Some ideas for some clever solutions would be appreciated!

答:
try this

```<code>    var newList = new List<KeyValuePair<string, string>>();

    var startDay = origList[0].Key;
    var endDay = startDay;
    var currentTime = origList[0].Value;
    foreach (var element in origList)
    {
        if (element.Value != currentTime)
        {
            var key = startDay + (startDay == endDay ? "" : "-" + endDay);
            newList.Add(new KeyValuePair<string, string>(key, currentTime));
            startDay = element.Key;
            currentTime = element.Value;
        }
        endDay = element.Key;
    }
    var lastKey = startDay + (startDay == endDay ? "" : "-" + endDay);
    newList.Add(new KeyValuePair<string, string>(lastKey, currentTime));
</code>```

result

```<code>    Mon-Wed 09:00-17:00
    Thu 08:00-18:00
    Fri 09:00-17:00
</code>```

Body:
try this

    var newList = new List<KeyValuePair<string, string>>();

    var startDay = origList[0].Key;
    var endDay = startDay;
    var currentTime = origList[0].Value;
    foreach (var element in origList)
    {
        if (element.Value != currentTime)
        {
            var key = startDay + (startDay == endDay ? "" : "-" + endDay);
            newList.Add(new KeyValuePair<string, string>(key, currentTime));
            startDay = element.Key;
            currentTime = element.Value;
        }
        endDay = element.Key;
    }
    var lastKey = startDay + (startDay == endDay ? "" : "-" + endDay);
    newList.Add(new KeyValuePair<string, string>(lastKey, currentTime));

result

    Mon-Wed 09:00-17:00
    Thu 08:00-18:00
    Fri 09:00-17:00


问:
WSO2 identity server - question for mfa for RDP
we are new  to identity management
and testing  wso2

is there a plugin or way to  use  WSo2  in premise idenity server and   MFA  for  various  RDP servers  logins?

答: Currently, there is no documented way to implement SSO for RDP servers with the WSO2 Identity Server.</p>


问:
Check if multiple dictionary keys are located in a string
Imagine having a txt file with like

5843092xxx289421xxx832175xxx...
```
<p>You have a dictionary with keys correspoding to letters
A am trying to search for each key within the string to output a message.</p>
```decoder = {5843092:'a', 289421:'b'}

with open( "code.txt","r") as fileTxt:
    fileTxt = fileTxt.readlines()

b = []
for key in decoder.keys():
    if key in fileTxt:
        b.append(decoder[key])
print(b)
```

this is what I have I feel like im on the right track but I am missing how to do each iteration maybe?

the goal output in this i.e. would be either a list or string of ab...

答:
There are two problems here:

You have a list of strings, and you're treating it as if it's one string.

You're building your output based on the order the keys appear in the decoder dictionary, rather than the order they appear in the input text.  That means the message will be all scrambled.

If the input text actually separates each key with a fixed string like xxx, the straightforward solution is to split on that string:

```<code>for line in fileTxt:
    print(' '.join(decoder.get(int(key), '?') for key in line.split('xxx')))
</code>```

Body:
Imagine having a txt file with like

5843092xxx289421xxx832175xxx...

You have a dictionary with keys correspoding to letters
A am trying to search for each key within the string to output a message.

decoder = {5843092:'a', 289421:'b'}

with open( "code.txt","r") as fileTxt:
    fileTxt = fileTxt.readlines()

b = []
for key in decoder.keys():
    if key in fileTxt:
        b.append(decoder[key])
print(b)

this is what I have I feel like im on the right track but I am missing how to do each iteration maybe?

the goal output in this i.e. would be either a list or string of ab...

Body:
There are two problems here:

You have a list of strings, and you're treating it as if it's one string.

You're building your output based on the order the keys appear in the decoder dictionary, rather than the order they appear in the input text.  That means the message will be all scrambled.

If the input text actually separates each key with a fixed string like xxx, the straightforward solution is to split on that string:

for line in fileTxt:
    print(' '.join(decoder.get(int(key), '?') for key in line.split('xxx')))


问:
Why is the account address from metamask coming back as undefined after storing it in useState()
I have this piece of code that is connecting to metamask wallet and sets the account address using useState().

```<code>const [currentAccount, setCurrentAccount] = useState("")
const connectWallet = async () => {
    try {
      if (!ethereum) return alert("Please install MetaMask.")

      const accounts = await ethereum.request({ method: "eth_requestAccounts" })

      setCurrentAccount(accounts[0])
      console.log(accounts)
      //   TODO:Add conditional statement to check if user has token
      navigate("/portfolio")
    } catch (error) {
      console.log(error)

      throw new Error("No ethereum object")
    }
  }

 console.log("current account", currentAccount)

  const returnCollection = async (currentAccount) => {
    const options = { method: 'GET', headers: { Accept: 'application/json' } };

    fetch(`https://api.opensea.io/api/v1/collections?asset_owner=${currentAccount}&offset=0&limit=300`, options)
      .then(response => response.json())
      .then(response => console.log("collection owned by current address", response))
      .catch(err => console.error(err));

 useEffect(() => {

    returnCollection(currentAccount)
  })

</code>```

The console is logging the account but when I try to pass it in the returnCollection call in useEffect() it comes back as undefined.

答:
It seems here, you are doing something like this:

```<code>useEffect(() => {

    returnCollection(currentAccount)
  })
</code>```

This will run after every rerender or every state change, and also initially when the component is first mounted, when currentAccount is "". Initially, current account is "", so you may not want to get the collection from "". Instead, maybe what you can do is create another state variable for the result of the returnConnection, and set the state variable to the result of the returnConnection, since you typically don't return results from useEffect, unless it's a cleanup function. Also, maybe you can check the state of currentAccount inside of the useEffect to make sure it's not "", before returning the result.

Body:
I have this piece of code that is connecting to metamask wallet and sets the account address using useState().

const [currentAccount, setCurrentAccount] = useState("")
const connectWallet = async () => {
    try {
      if (!ethereum) return alert("Please install MetaMask.")

      const accounts = await ethereum.request({ method: "eth_requestAccounts" })

      setCurrentAccount(accounts[0])
      console.log(accounts)
      //   TODO:Add conditional statement to check if user has token
      navigate("/portfolio")
    } catch (error) {
      console.log(error)

      throw new Error("No ethereum object")
    }
  }

 console.log("current account", currentAccount)

  const returnCollection = async (currentAccount) => {
    const options = { method: 'GET', headers: { Accept: 'application/json' } };

    fetch(`https://api.opensea.io/api/v1/collections?asset_owner=${currentAccount}&offset=0&limit=300`, options)
      .then(response => response.json())
      .then(response => console.log("collection owned by current address", response))
      .catch(err => console.error(err));

 useEffect(() => {

    returnCollection(currentAccount)
  })

The console is logging the account but when I try to pass it in the returnCollection call in useEffect() it comes back as undefined.

Body:
It seems here, you are doing something like this:

useEffect(() => {

    returnCollection(currentAccount)
  })

This will run after every rerender or every state change, and also initially when the component is first mounted, when currentAccount is "". Initially, current account is "", so you may not want to get the collection from "". Instead, maybe what you can do is create another state variable for the result of the returnConnection, and set the state variable to the result of the returnConnection, since you typically don't return results from useEffect, unless it's a cleanup function. Also, maybe you can check the state of currentAccount inside of the useEffect to make sure it's not "", before returning the result.


问:
PowerShell Core proxy issues
I just wanted to share this with you all. If I knew what to ask for, I would have created a ticket up front. But what I found online was partly misleading.
It was a combination of searching and trying, until I finally found the solution.

This issues was related to running PowerShell Core on a corporate machine, initially setup for Proxy use.

Problem description

After fresh installation of PowerShell Core, Install-Module where unable to resolve package source and Invoke-WebRequest "any-external-url" reported "No such host". This is all under Windows 10.

答:
Solution to my issue

I had to do all of this to bypass the proxy.

First was to unset the Environment Variable for the proxy. (Maybe you also need to do this for HTTP_PROXY environment variable)

Set-Item -Path Env:HTTPS_PROXY -Value ""

Reset proxy for HttpClient

[System.Net.Http.HttpClient]::DefaultProxy = New-Object System.Net.WebProxy($null)

Reset proxy for HttpWebRequest

[System.Net.HttpWebRequest]::DefaultWebProxy = New-Object System.Net.WebProxy($null)

I ended up adding them to the PowerShell 7 profile.

Hope it save some time for at least one more soul. :)

Title: PowerShell Core proxy issues


问:
Assign values by matching two lists in excel
I have these two list and I am trying to assign values i.e 11,22,33 to the second list that matches values with the first list.

So, for examples in the second list if its "Industrials" it would take value of 11, "Resources" would take value of 33 and so on.

I have tried index match but I believe it won't work in this case. Any help or ideas would be great.

答:
So you may try using any one of the following formulas as shown in the image below

APPROACH ONE - FORMULA USED IN CELL E2

```<code>=INDEX($B$2:$B$8,MATCH(LEFT($D2,3)&"*",$A$2:$A$8,0))
</code>```

APPROACH TWO - FORMULA USED IN CELL F2 (O365 & EXCEL 2021)

```<code>=XLOOKUP(LEFT($D2,3)&"*",$A$2:$A$8,$B$2:$B$8,,2)
</code>```

APPROACH THREE - FORMULA USED IN CELL G2

```<code>=VLOOKUP(LEFT($D2,3)&"*",$A$2:$B$8,2,0)
</code>```

APPROACH FOUR - FORMULA USED IN CELL H2

```<code>=LOOKUP(2,1/(LEFT(D2,3)=LEFT($A$2:$A$8,3)),$B$2:$B$8)
</code>```

Body:
So you may try using any one of the following formulas as shown in the image below

APPROACH ONE - FORMULA USED IN CELL E2

=INDEX($B$2:$B$8,MATCH(LEFT($D2,3)&"*",$A$2:$A$8,0))

APPROACH TWO - FORMULA USED IN CELL F2 (O365 & EXCEL 2021)

=XLOOKUP(LEFT($D2,3)&"*",$A$2:$A$8,$B$2:$B$8,,2)

APPROACH THREE - FORMULA USED IN CELL G2

=VLOOKUP(LEFT($D2,3)&"*",$A$2:$B$8,2,0)

APPROACH FOUR - FORMULA USED IN CELL H2

=LOOKUP(2,1/(LEFT(D2,3)=LEFT($A$2:$A$8,3)),$B$2:$B$8)


问:
brownie：ValueError: execution reverted: VM Exception while processing transaction: revert
Macbook Pro : Monterey

Intel Core i7

Brownie v1.17.2

I am learning solidity according to reference(https://www.youtube.com/watch?v=M576WGiDBdQ&t=25510s).

What I tried to do here, is use brownie to deploy a contract(FundMe) in a script (deploy.py),then write a test script(scripts/fund_and_withdraw.py.py)

I met the same error,the MockV3Aggregator deployed successfully, but the getEntrancePrice is 0
Googled it find this answer,don't quite follow.(https://ethereum.stackexchange.com/questions/114889/deploying-ganache-local-w-brownie-vm-exception-while-processing-transaction-in)

getPrice() isn't returning a number you want from the mock, somewhere in the vicinity of 2B. Think this is a bug with the Ganache implementation- performing the calculation (minimumUSD * precision) / price in getEntranceFee() gives you a number less than 1- and, since Solidity can't handle floats, Solidity simply sees it as a 0, and the whole thing errors out.

scripts/fund_and_withdraw.py

```<code>from brownie import FundMe
from scripts.helpful_scripts import get_account

def fund():
    fund_me = FundMe[-1]

    account = get_account()

    entrance_fee = fund_me.getEntranceFee()
    print(f"The entrance fee is : {entrance_fee} !")
    print("funding")
    fund_me.fund({"from": account, "value": entrance_fee})
    print(f"Funded {entrance_fee} !")

def withdraw():
    fund_me = FundMe[-1]
    account = get_account()
    fund_me.withdraw({"from": account})

def main():
    fund()
    withdraw()

</code>```

deploy.py

```<code>from brownie import FundMe, network, config, MockV3Aggregator
from scripts.helpful_scripts import (
    get_account,
    deploy_mocks,
    LOCAL_BLOCKCHAIN_ENVIRONMENT,
)

def deploy_fund_me():
    account = get_account()
    # if we have a persistent network like rinkeby,use the associated address
    # otherwise ,deploy mocks
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENT:
        price_feed_address = config["networks"][network.show_active()][
            "eth_usd_price_feed"
        ]
    else:
        deploy_mocks()
        # just use the latest mockV3Aggregator
        price_feed_address = MockV3Aggregator[-1].address
        print("***********************************************************")
        print(f"MockVeAggrator's address is {price_feed_address}")

    fund_me = FundMe.deploy(
        price_feed_address,
        {"from": account},
        publish_source=config["networks"][network.show_active()].get("verify"),
    )
    print("***********************************************************")
    print(f"The Ether price is :{fund_me.getPrice()}\n")
    print(f"Contract deployed to {fund_me.address}\n")
    entrance_fee = fund_me.getEntranceFee()
    print("***********************************************************")
    print(f"The entrance fee is : {entrance_fee} !\n")
    return fund_me

def main():
    deploy_fund_me()
</code>```

FundMe.sol

```<code>// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

// we need tell brownie @chainlink means == what input in config,need to tell compiler

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

import "@chainlink/contracts/src/v0.6/vendor/SafeMathChainlink.sol";

contract FundMe {
    //using SafeMathChainlink for uint256;

    mapping(address => uint256) public addressToAmountFunded;
    address[] public funders;
    address public owner;
    AggregatorV3Interface public priceFeed;

    // if you're following along with the freecodecamp video
    // Please see https://github.com/PatrickAlphaC/fund_me
    // to get the starting solidity contract code, it'll be slightly different than this!
    constructor(address _priceFeed) {
        // make price feed a parameter
        priceFeed = AggregatorV3Interface(_priceFeed);
        owner = msg.sender;
    }

    function fund() public payable {
        uint256 mimimumUSD = 50 * 10**18;
        require(
            getConversionRate(msg.value) >= mimimumUSD,
            "You need to spend more ETH!"
        );
        addressToAmountFunded[msg.sender] += msg.value;
        funders.push(msg.sender);
    }

    function getVersion() public view returns (uint256) {
        return priceFeed.version();
    }

    function getPrice() public view returns (uint256) {
        (, int256 answer, , , ) = priceFeed.latestRoundData();
        return uint256(answer * 10000000000);
    }

    // 1000000000
    function getConversionRate(uint256 ethAmount)
        public
        view
        returns (uint256)
    {
        uint256 ethPrice = getPrice();
        uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
        return ethAmountInUsd;
    }

    function getEntranceFee() public view returns (uint256) {
        // mimimumUSD
        uint256 mimimumUSD = 50 * 10**18;
        uint256 price = getPrice();
        uint256 precision = 1 * 10**18;
        return (mimimumUSD * precision) / price;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function withdraw() public payable onlyOwner {
        payable(msg.sender).transfer(address(this).balance);

        for (
            uint256 funderIndex = 0;
            funderIndex < funders.length;
            funderIndex++
        ) {
            address funder = funders[funderIndex];
            addressToAmountFunded[funder] = 0;
        }
        funders = new address[](0);
    }
}

</code>```

update
the error disappear magicly (may be come back later),right now the error info is :list out of index
actually i faced the same error in another project (Brownie test IndexError: list index out of range)

according the answer and brownie docs, I need to add account.
what confused me is if I launched the ganache local blockchain already ,why I still need to add account or I added the wrong way?

答:
If you're getting the getEntrancePrice as 0, remove the web3.toWei function in this part right here in the helpful_scripts.py file:

```<code>MockV3Aggregator.deploy(
            DECIMALS, Web3.toWei(STARTING_PRICE, "ether"), {"from": get_account()}
        )
</code>```

and change to this:

```<code>MockV3Aggregator.deploy(DECIMALS, STARTING_PRICE, {"from": get_account()})
</code>```

Since you already specified at the top(as global variables) that the mock price output decimal place would be 8 and added the additional 8 zeros after 2000 to send the mock constructor an initial price with 8 decimal places, by leaving the toWei function your adding an additional 18 decimal places for a total of 26 which is wrong.

In addition, you're output after deploying the mock is being added another 10 decimal places for a total of 36.

```<code>DECIMALS = 8
STARTING_PRICE = 200000000000
</code>```

My guess is the reason you're getting 0 is because you exceeded the size allowed by the uint8 decimal variable or maybe sending the initial price with 26 decimal places to the constructor takes more gas fees than the gas limit allowed to each block and transaction by ganache. Someone clarify if able!

Body:
Macbook Pro : Monterey

Intel Core i7

Brownie v1.17.2

I am learning solidity according to reference(https://www.youtube.com/watch?v=M576WGiDBdQ&t=25510s).

What I tried to do here, is use brownie to deploy a contract(FundMe) in a script (deploy.py),then write a test script(scripts/fund_and_withdraw.py.py)

I met the same error,the MockV3Aggregator deployed successfully, but the getEntrancePrice is 0
Googled it find this answer,don't quite follow.(https://ethereum.stackexchange.com/questions/114889/deploying-ganache-local-w-brownie-vm-exception-while-processing-transaction-in)

getPrice() isn't returning a number you want from the mock, somewhere in the vicinity of 2B. Think this is a bug with the Ganache implementation- performing the calculation (minimumUSD * precision) / price in getEntranceFee() gives you a number less than 1- and, since Solidity can't handle floats, Solidity simply sees it as a 0, and the whole thing errors out.

scripts/fund_and_withdraw.py

from brownie import FundMe
from scripts.helpful_scripts import get_account

def fund():
    fund_me = FundMe[-1]

    account = get_account()

    entrance_fee = fund_me.getEntranceFee()
    print(f"The entrance fee is : {entrance_fee} !")
    print("funding")
    fund_me.fund({"from": account, "value": entrance_fee})
    print(f"Funded {entrance_fee} !")

def withdraw():
    fund_me = FundMe[-1]
    account = get_account()
    fund_me.withdraw({"from": account})

def main():
    fund()
    withdraw()

deploy.py

from brownie import FundMe, network, config, MockV3Aggregator
from scripts.helpful_scripts import (
    get_account,
    deploy_mocks,
    LOCAL_BLOCKCHAIN_ENVIRONMENT,
)

def deploy_fund_me():
    account = get_account()
    # if we have a persistent network like rinkeby,use the associated address
    # otherwise ,deploy mocks
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENT:
        price_feed_address = config["networks"][network.show_active()][
            "eth_usd_price_feed"
        ]
    else:
        deploy_mocks()
        # just use the latest mockV3Aggregator
        price_feed_address = MockV3Aggregator[-1].address
        print("***********************************************************")
        print(f"MockVeAggrator's address is {price_feed_address}")

    fund_me = FundMe.deploy(
        price_feed_address,
        {"from": account},
        publish_source=config["networks"][network.show_active()].get("verify"),
    )
    print("***********************************************************")
    print(f"The Ether price is :{fund_me.getPrice()}\n")
    print(f"Contract deployed to {fund_me.address}\n")
    entrance_fee = fund_me.getEntranceFee()
    print("***********************************************************")
    print(f"The entrance fee is : {entrance_fee} !\n")
    return fund_me

def main():
    deploy_fund_me()

FundMe.sol

// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

// we need tell brownie @chainlink means == what input in config,need to tell compiler

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";

import "@chainlink/contracts/src/v0.6/vendor/SafeMathChainlink.sol";

contract FundMe {
    //using SafeMathChainlink for uint256;

    mapping(address => uint256) public addressToAmountFunded;
    address[] public funders;
    address public owner;
    AggregatorV3Interface public priceFeed;

    // if you're following along with the freecodecamp video
    // Please see https://github.com/PatrickAlphaC/fund_me
    // to get the starting solidity contract code, it'll be slightly different than this!
    constructor(address _priceFeed) {
        // make price feed a parameter
        priceFeed = AggregatorV3Interface(_priceFeed);
        owner = msg.sender;
    }

    function fund() public payable {
        uint256 mimimumUSD = 50 * 10**18;
        require(
            getConversionRate(msg.value) >= mimimumUSD,
            "You need to spend more ETH!"
        );
        addressToAmountFunded[msg.sender] += msg.value;
        funders.push(msg.sender);
    }

    function getVersion() public view returns (uint256) {
        return priceFeed.version();
    }

    function getPrice() public view returns (uint256) {
        (, int256 answer, , , ) = priceFeed.latestRoundData();
        return uint256(answer * 10000000000);
    }

    // 1000000000
    function getConversionRate(uint256 ethAmount)
        public
        view
        returns (uint256)
    {
        uint256 ethPrice = getPrice();
        uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
        return ethAmountInUsd;
    }

    function getEntranceFee() public view returns (uint256) {
        // mimimumUSD
        uint256 mimimumUSD = 50 * 10**18;
        uint256 price = getPrice();
        uint256 precision = 1 * 10**18;
        return (mimimumUSD * precision) / price;
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function withdraw() public payable onlyOwner {
        payable(msg.sender).transfer(address(this).balance);

        for (
            uint256 funderIndex = 0;
            funderIndex < funders.length;
            funderIndex++
        ) {
            address funder = funders[funderIndex];
            addressToAmountFunded[funder] = 0;
        }
        funders = new address[](0);
    }
}

update
the error disappear magicly (may be come back later),right now the error info is :list out of index
actually i faced the same error in another project (Brownie test IndexError: list index out of range)

according the answer and brownie docs, I need to add account.
what confused me is if I launched the ganache local blockchain already ,why I still need to add account or I added the wrong way?

Body:
If you're getting the getEntrancePrice as 0, remove the web3.toWei function in this part right here in the helpful_scripts.py file:

MockV3Aggregator.deploy(
            DECIMALS, Web3.toWei(STARTING_PRICE, "ether"), {"from": get_account()}
        )

and change to this:

MockV3Aggregator.deploy(DECIMALS, STARTING_PRICE, {"from": get_account()})

Since you already specified at the top(as global variables) that the mock price output decimal place would be 8 and added the additional 8 zeros after 2000 to send the mock constructor an initial price with 8 decimal places, by leaving the toWei function your adding an additional 18 decimal places for a total of 26 which is wrong.

In addition, you're output after deploying the mock is being added another 10 decimal places for a total of 36.

DECIMALS = 8
STARTING_PRICE = 200000000000

My guess is the reason you're getting 0 is because you exceeded the size allowed by the uint8 decimal variable or maybe sending the initial price with 26 decimal places to the constructor takes more gas fees than the gas limit allowed to each block and transaction by ganache. Someone clarify if able!